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 931da177e4SLinus Torvalds #include <asm/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); 1211da177e4SLinus Torvalds static unsigned int 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 /* 1661da177e4SLinus Torvalds * Statistics counters of the socket lists 1671da177e4SLinus Torvalds */ 1681da177e4SLinus Torvalds 169c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use); 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds /* 17289bddce5SStephen Hemminger * Support routines. 17389bddce5SStephen Hemminger * Move socket addresses back and forth across the kernel/user 1741da177e4SLinus Torvalds * divide and look after the messy bits. 1751da177e4SLinus Torvalds */ 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds /** 1781da177e4SLinus Torvalds * move_addr_to_kernel - copy a socket address into kernel space 1791da177e4SLinus Torvalds * @uaddr: Address in user space 1801da177e4SLinus Torvalds * @kaddr: Address in kernel space 1811da177e4SLinus Torvalds * @ulen: Length in user space 1821da177e4SLinus Torvalds * 1831da177e4SLinus Torvalds * The address is copied into kernel space. If the provided address is 1841da177e4SLinus Torvalds * too long an error code of -EINVAL is returned. If the copy gives 1851da177e4SLinus Torvalds * invalid addresses -EFAULT is returned. On a success 0 is returned. 1861da177e4SLinus Torvalds */ 1871da177e4SLinus Torvalds 18843db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr) 1891da177e4SLinus Torvalds { 190230b1839SYOSHIFUJI Hideaki if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) 1911da177e4SLinus Torvalds return -EINVAL; 1921da177e4SLinus Torvalds if (ulen == 0) 1931da177e4SLinus Torvalds return 0; 1941da177e4SLinus Torvalds if (copy_from_user(kaddr, uaddr, ulen)) 1951da177e4SLinus Torvalds return -EFAULT; 1963ec3b2fbSDavid Woodhouse return audit_sockaddr(ulen, kaddr); 1971da177e4SLinus Torvalds } 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds /** 2001da177e4SLinus Torvalds * move_addr_to_user - copy an address to user space 2011da177e4SLinus Torvalds * @kaddr: kernel space address 2021da177e4SLinus Torvalds * @klen: length of address in kernel 2031da177e4SLinus Torvalds * @uaddr: user space address 2041da177e4SLinus Torvalds * @ulen: pointer to user length field 2051da177e4SLinus Torvalds * 2061da177e4SLinus Torvalds * The value pointed to by ulen on entry is the buffer length available. 2071da177e4SLinus Torvalds * This is overwritten with the buffer space used. -EINVAL is returned 2081da177e4SLinus Torvalds * if an overlong buffer is specified or a negative buffer size. -EFAULT 2091da177e4SLinus Torvalds * is returned if either the buffer or the length field are not 2101da177e4SLinus Torvalds * accessible. 2111da177e4SLinus Torvalds * After copying the data up to the limit the user specifies, the true 2121da177e4SLinus Torvalds * length of the data is written over the length limit the user 2131da177e4SLinus Torvalds * specified. Zero is returned for a success. 2141da177e4SLinus Torvalds */ 2151da177e4SLinus Torvalds 21643db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, 21711165f14Sstephen hemminger void __user *uaddr, int __user *ulen) 2181da177e4SLinus Torvalds { 2191da177e4SLinus Torvalds int err; 2201da177e4SLinus Torvalds int len; 2211da177e4SLinus Torvalds 22268c6beb3SHannes Frederic Sowa BUG_ON(klen > sizeof(struct sockaddr_storage)); 22389bddce5SStephen Hemminger err = get_user(len, ulen); 22489bddce5SStephen Hemminger if (err) 2251da177e4SLinus Torvalds return err; 2261da177e4SLinus Torvalds if (len > klen) 2271da177e4SLinus Torvalds len = klen; 22868c6beb3SHannes Frederic Sowa if (len < 0) 2291da177e4SLinus Torvalds return -EINVAL; 23089bddce5SStephen Hemminger if (len) { 231d6fe3945SSteve Grubb if (audit_sockaddr(klen, kaddr)) 232d6fe3945SSteve Grubb return -ENOMEM; 2331da177e4SLinus Torvalds if (copy_to_user(uaddr, kaddr, len)) 2341da177e4SLinus Torvalds return -EFAULT; 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds /* 2371da177e4SLinus Torvalds * "fromlen shall refer to the value before truncation.." 2381da177e4SLinus Torvalds * 1003.1g 2391da177e4SLinus Torvalds */ 2401da177e4SLinus Torvalds return __put_user(klen, ulen); 2411da177e4SLinus Torvalds } 2421da177e4SLinus Torvalds 243e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly; 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb) 2461da177e4SLinus Torvalds { 2471da177e4SLinus Torvalds struct socket_alloc *ei; 248eaefd110SEric Dumazet struct socket_wq *wq; 24989bddce5SStephen Hemminger 250e94b1766SChristoph Lameter ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 2511da177e4SLinus Torvalds if (!ei) 2521da177e4SLinus Torvalds return NULL; 253eaefd110SEric Dumazet wq = kmalloc(sizeof(*wq), GFP_KERNEL); 254eaefd110SEric Dumazet if (!wq) { 25543815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 25643815482SEric Dumazet return NULL; 25743815482SEric Dumazet } 258eaefd110SEric Dumazet init_waitqueue_head(&wq->wait); 259eaefd110SEric Dumazet wq->fasync_list = NULL; 260574aab1eSNicolai Stange wq->flags = 0; 261eaefd110SEric Dumazet RCU_INIT_POINTER(ei->socket.wq, wq); 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds ei->socket.state = SS_UNCONNECTED; 2641da177e4SLinus Torvalds ei->socket.flags = 0; 2651da177e4SLinus Torvalds ei->socket.ops = NULL; 2661da177e4SLinus Torvalds ei->socket.sk = NULL; 2671da177e4SLinus Torvalds ei->socket.file = NULL; 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds return &ei->vfs_inode; 2701da177e4SLinus Torvalds } 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode) 2731da177e4SLinus Torvalds { 27443815482SEric Dumazet struct socket_alloc *ei; 275eaefd110SEric Dumazet struct socket_wq *wq; 27643815482SEric Dumazet 27743815482SEric Dumazet ei = container_of(inode, struct socket_alloc, vfs_inode); 278eaefd110SEric Dumazet wq = rcu_dereference_protected(ei->socket.wq, 1); 27961845220SLai Jiangshan kfree_rcu(wq, rcu); 28043815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 28351cc5068SAlexey Dobriyan static void init_once(void *foo) 2841da177e4SLinus Torvalds { 2851da177e4SLinus Torvalds struct socket_alloc *ei = (struct socket_alloc *)foo; 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode); 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvalds static int init_inodecache(void) 2911da177e4SLinus Torvalds { 2921da177e4SLinus Torvalds sock_inode_cachep = kmem_cache_create("sock_inode_cache", 2931da177e4SLinus Torvalds sizeof(struct socket_alloc), 29489bddce5SStephen Hemminger 0, 29589bddce5SStephen Hemminger (SLAB_HWCACHE_ALIGN | 29689bddce5SStephen Hemminger SLAB_RECLAIM_ACCOUNT | 2975d097056SVladimir Davydov SLAB_MEM_SPREAD | SLAB_ACCOUNT), 29820c2df83SPaul Mundt init_once); 2991da177e4SLinus Torvalds if (sock_inode_cachep == NULL) 3001da177e4SLinus Torvalds return -ENOMEM; 3011da177e4SLinus Torvalds return 0; 3021da177e4SLinus Torvalds } 3031da177e4SLinus Torvalds 304b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = { 3051da177e4SLinus Torvalds .alloc_inode = sock_alloc_inode, 3061da177e4SLinus Torvalds .destroy_inode = sock_destroy_inode, 3071da177e4SLinus Torvalds .statfs = simple_statfs, 3081da177e4SLinus Torvalds }; 3091da177e4SLinus Torvalds 310c23fbb6bSEric Dumazet /* 311c23fbb6bSEric Dumazet * sockfs_dname() is called from d_path(). 312c23fbb6bSEric Dumazet */ 313c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) 314c23fbb6bSEric Dumazet { 315c23fbb6bSEric Dumazet return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", 316c5ef6035SDavid Howells d_inode(dentry)->i_ino); 317c23fbb6bSEric Dumazet } 318c23fbb6bSEric Dumazet 3193ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = { 320c23fbb6bSEric Dumazet .d_dname = sockfs_dname, 3211da177e4SLinus Torvalds }; 3221da177e4SLinus Torvalds 323bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler, 324bba0bd31SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 325bba0bd31SAndreas Gruenbacher const char *suffix, void *value, size_t size) 326bba0bd31SAndreas Gruenbacher { 327bba0bd31SAndreas Gruenbacher if (value) { 328bba0bd31SAndreas Gruenbacher if (dentry->d_name.len + 1 > size) 329bba0bd31SAndreas Gruenbacher return -ERANGE; 330bba0bd31SAndreas Gruenbacher memcpy(value, dentry->d_name.name, dentry->d_name.len + 1); 331bba0bd31SAndreas Gruenbacher } 332bba0bd31SAndreas Gruenbacher return dentry->d_name.len + 1; 333bba0bd31SAndreas Gruenbacher } 334bba0bd31SAndreas Gruenbacher 335bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname" 336bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX) 337bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1) 338bba0bd31SAndreas Gruenbacher 339bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = { 340bba0bd31SAndreas Gruenbacher .name = XATTR_NAME_SOCKPROTONAME, 341bba0bd31SAndreas Gruenbacher .get = sockfs_xattr_get, 342bba0bd31SAndreas Gruenbacher }; 343bba0bd31SAndreas Gruenbacher 3444a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler, 3454a590153SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 3464a590153SAndreas Gruenbacher const char *suffix, const void *value, 3474a590153SAndreas Gruenbacher size_t size, int flags) 3484a590153SAndreas Gruenbacher { 3494a590153SAndreas Gruenbacher /* Handled by LSM. */ 3504a590153SAndreas Gruenbacher return -EAGAIN; 3514a590153SAndreas Gruenbacher } 3524a590153SAndreas Gruenbacher 3534a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = { 3544a590153SAndreas Gruenbacher .prefix = XATTR_SECURITY_PREFIX, 3554a590153SAndreas Gruenbacher .set = sockfs_security_xattr_set, 3564a590153SAndreas Gruenbacher }; 3574a590153SAndreas Gruenbacher 358bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = { 359bba0bd31SAndreas Gruenbacher &sockfs_xattr_handler, 3604a590153SAndreas Gruenbacher &sockfs_security_xattr_handler, 361bba0bd31SAndreas Gruenbacher NULL 362bba0bd31SAndreas Gruenbacher }; 363bba0bd31SAndreas Gruenbacher 364c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type, 365c74a1cbbSAl Viro int flags, const char *dev_name, void *data) 366c74a1cbbSAl Viro { 367bba0bd31SAndreas Gruenbacher return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops, 368bba0bd31SAndreas Gruenbacher sockfs_xattr_handlers, 369c74a1cbbSAl Viro &sockfs_dentry_operations, SOCKFS_MAGIC); 370c74a1cbbSAl Viro } 371c74a1cbbSAl Viro 372c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly; 373c74a1cbbSAl Viro 374c74a1cbbSAl Viro static struct file_system_type sock_fs_type = { 375c74a1cbbSAl Viro .name = "sockfs", 376c74a1cbbSAl Viro .mount = sockfs_mount, 377c74a1cbbSAl Viro .kill_sb = kill_anon_super, 378c74a1cbbSAl Viro }; 379c74a1cbbSAl Viro 3801da177e4SLinus Torvalds /* 3811da177e4SLinus Torvalds * Obtains the first available file descriptor and sets it up for use. 3821da177e4SLinus Torvalds * 38339d8c1b6SDavid S. Miller * These functions create file structures and maps them to fd space 38439d8c1b6SDavid S. Miller * of the current process. On success it returns file descriptor 3851da177e4SLinus Torvalds * and file struct implicitly stored in sock->file. 3861da177e4SLinus Torvalds * Note that another thread may close file descriptor before we return 3871da177e4SLinus Torvalds * from this function. We use the fact that now we do not refer 3881da177e4SLinus Torvalds * to socket after mapping. If one day we will need it, this 3891da177e4SLinus Torvalds * function will increment ref. count on file by 1. 3901da177e4SLinus Torvalds * 3911da177e4SLinus Torvalds * In any case returned fd MAY BE not valid! 3921da177e4SLinus Torvalds * This race condition is unavoidable 3931da177e4SLinus Torvalds * with shared fd spaces, we cannot solve it inside kernel, 3941da177e4SLinus Torvalds * but we take care of internal coherence yet. 3951da177e4SLinus Torvalds */ 3961da177e4SLinus Torvalds 397aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) 3981da177e4SLinus Torvalds { 3997cbe66b6SAl Viro struct qstr name = { .name = "" }; 4002c48b9c4SAl Viro struct path path; 4017cbe66b6SAl Viro struct file *file; 4021da177e4SLinus Torvalds 403600e1779SMasatake YAMATO if (dname) { 404600e1779SMasatake YAMATO name.name = dname; 405600e1779SMasatake YAMATO name.len = strlen(name.name); 406600e1779SMasatake YAMATO } else if (sock->sk) { 407600e1779SMasatake YAMATO name.name = sock->sk->sk_prot_creator->name; 408600e1779SMasatake YAMATO name.len = strlen(name.name); 409600e1779SMasatake YAMATO } 4104b936885SNick Piggin path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); 41128407630SAl Viro if (unlikely(!path.dentry)) 41228407630SAl Viro return ERR_PTR(-ENOMEM); 4132c48b9c4SAl Viro path.mnt = mntget(sock_mnt); 41439d8c1b6SDavid S. Miller 4152c48b9c4SAl Viro d_instantiate(path.dentry, SOCK_INODE(sock)); 416cc3808f8SAl Viro 4172c48b9c4SAl Viro file = alloc_file(&path, FMODE_READ | FMODE_WRITE, 418cc3808f8SAl Viro &socket_file_ops); 419b5ffe634SViresh Kumar if (IS_ERR(file)) { 420cc3808f8SAl Viro /* drop dentry, keep inode */ 421c5ef6035SDavid Howells ihold(d_inode(path.dentry)); 4222c48b9c4SAl Viro path_put(&path); 42339b65252SAnatol Pomozov return file; 424cc3808f8SAl Viro } 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvalds sock->file = file; 42777d27200SUlrich Drepper file->f_flags = O_RDWR | (flags & O_NONBLOCK); 42807dc3f07SBenjamin LaHaise file->private_data = sock; 42928407630SAl Viro return file; 4301da177e4SLinus Torvalds } 43156b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file); 4321da177e4SLinus Torvalds 43356b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags) 43439d8c1b6SDavid S. Miller { 43539d8c1b6SDavid S. Miller struct file *newfile; 43628407630SAl Viro int fd = get_unused_fd_flags(flags); 43728407630SAl Viro if (unlikely(fd < 0)) 4381da177e4SLinus Torvalds return fd; 4391da177e4SLinus Torvalds 440aab174f0SLinus Torvalds newfile = sock_alloc_file(sock, flags, NULL); 44128407630SAl Viro if (likely(!IS_ERR(newfile))) { 4421da177e4SLinus Torvalds fd_install(fd, newfile); 4431da177e4SLinus Torvalds return fd; 4441da177e4SLinus Torvalds } 44528407630SAl Viro 44628407630SAl Viro put_unused_fd(fd); 44728407630SAl Viro return PTR_ERR(newfile); 4481da177e4SLinus Torvalds } 4491da177e4SLinus Torvalds 450406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err) 4516cb153caSBenjamin LaHaise { 4526cb153caSBenjamin LaHaise if (file->f_op == &socket_file_ops) 4536cb153caSBenjamin LaHaise return file->private_data; /* set in sock_map_fd */ 4546cb153caSBenjamin LaHaise 4556cb153caSBenjamin LaHaise *err = -ENOTSOCK; 4566cb153caSBenjamin LaHaise return NULL; 4576cb153caSBenjamin LaHaise } 458406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file); 4596cb153caSBenjamin LaHaise 4601da177e4SLinus Torvalds /** 4611da177e4SLinus Torvalds * sockfd_lookup - Go from a file number to its socket slot 4621da177e4SLinus Torvalds * @fd: file handle 4631da177e4SLinus Torvalds * @err: pointer to an error code return 4641da177e4SLinus Torvalds * 4651da177e4SLinus Torvalds * The file handle passed in is locked and the socket it is bound 4661da177e4SLinus Torvalds * too is returned. If an error occurs the err pointer is overwritten 4671da177e4SLinus Torvalds * with a negative errno code and NULL is returned. The function checks 4681da177e4SLinus Torvalds * for both invalid handles and passing a handle which is not a socket. 4691da177e4SLinus Torvalds * 4701da177e4SLinus Torvalds * On a success the socket object pointer is returned. 4711da177e4SLinus Torvalds */ 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err) 4741da177e4SLinus Torvalds { 4751da177e4SLinus Torvalds struct file *file; 4761da177e4SLinus Torvalds struct socket *sock; 4771da177e4SLinus Torvalds 47889bddce5SStephen Hemminger file = fget(fd); 47989bddce5SStephen Hemminger if (!file) { 4801da177e4SLinus Torvalds *err = -EBADF; 4811da177e4SLinus Torvalds return NULL; 4821da177e4SLinus Torvalds } 48389bddce5SStephen Hemminger 4846cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4856cb153caSBenjamin LaHaise if (!sock) 4861da177e4SLinus Torvalds fput(file); 4876cb153caSBenjamin LaHaise return sock; 4881da177e4SLinus Torvalds } 489c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup); 4901da177e4SLinus Torvalds 4916cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) 4926cb153caSBenjamin LaHaise { 49300e188efSAl Viro struct fd f = fdget(fd); 4946cb153caSBenjamin LaHaise struct socket *sock; 4956cb153caSBenjamin LaHaise 4963672558cSHua Zhong *err = -EBADF; 49700e188efSAl Viro if (f.file) { 49800e188efSAl Viro sock = sock_from_file(f.file, err); 49900e188efSAl Viro if (likely(sock)) { 50000e188efSAl Viro *fput_needed = f.flags; 5011da177e4SLinus Torvalds return sock; 50200e188efSAl Viro } 50300e188efSAl Viro fdput(f); 5046cb153caSBenjamin LaHaise } 5056cb153caSBenjamin LaHaise return NULL; 5061da177e4SLinus Torvalds } 5071da177e4SLinus Torvalds 508600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, 509600e1779SMasatake YAMATO size_t size) 510600e1779SMasatake YAMATO { 511600e1779SMasatake YAMATO ssize_t len; 512600e1779SMasatake YAMATO ssize_t used = 0; 513600e1779SMasatake YAMATO 514c5ef6035SDavid Howells len = security_inode_listsecurity(d_inode(dentry), buffer, size); 515600e1779SMasatake YAMATO if (len < 0) 516600e1779SMasatake YAMATO return len; 517600e1779SMasatake YAMATO used += len; 518600e1779SMasatake YAMATO if (buffer) { 519600e1779SMasatake YAMATO if (size < used) 520600e1779SMasatake YAMATO return -ERANGE; 521600e1779SMasatake YAMATO buffer += len; 522600e1779SMasatake YAMATO } 523600e1779SMasatake YAMATO 524600e1779SMasatake YAMATO len = (XATTR_NAME_SOCKPROTONAME_LEN + 1); 525600e1779SMasatake YAMATO used += len; 526600e1779SMasatake YAMATO if (buffer) { 527600e1779SMasatake YAMATO if (size < used) 528600e1779SMasatake YAMATO return -ERANGE; 529600e1779SMasatake YAMATO memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len); 530600e1779SMasatake YAMATO buffer += len; 531600e1779SMasatake YAMATO } 532600e1779SMasatake YAMATO 533600e1779SMasatake YAMATO return used; 534600e1779SMasatake YAMATO } 535600e1779SMasatake YAMATO 53686741ec2SLorenzo Colitti int sockfs_setattr(struct dentry *dentry, struct iattr *iattr) 53786741ec2SLorenzo Colitti { 53886741ec2SLorenzo Colitti int err = simple_setattr(dentry, iattr); 53986741ec2SLorenzo Colitti 54086741ec2SLorenzo Colitti if (!err) { 54186741ec2SLorenzo Colitti struct socket *sock = SOCKET_I(d_inode(dentry)); 54286741ec2SLorenzo Colitti 54386741ec2SLorenzo Colitti sock->sk->sk_uid = iattr->ia_uid; 54486741ec2SLorenzo Colitti } 54586741ec2SLorenzo Colitti 54686741ec2SLorenzo Colitti return err; 54786741ec2SLorenzo Colitti } 54886741ec2SLorenzo Colitti 549600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = { 550600e1779SMasatake YAMATO .listxattr = sockfs_listxattr, 55186741ec2SLorenzo Colitti .setattr = sockfs_setattr, 552600e1779SMasatake YAMATO }; 553600e1779SMasatake YAMATO 5541da177e4SLinus Torvalds /** 5551da177e4SLinus Torvalds * sock_alloc - allocate a socket 5561da177e4SLinus Torvalds * 5571da177e4SLinus Torvalds * Allocate a new inode and socket object. The two are bound together 5581da177e4SLinus Torvalds * and initialised. The socket is then returned. If we are out of inodes 5591da177e4SLinus Torvalds * NULL is returned. 5601da177e4SLinus Torvalds */ 5611da177e4SLinus Torvalds 562f4a00aacSTom Herbert struct socket *sock_alloc(void) 5631da177e4SLinus Torvalds { 5641da177e4SLinus Torvalds struct inode *inode; 5651da177e4SLinus Torvalds struct socket *sock; 5661da177e4SLinus Torvalds 567a209dfc7SEric Dumazet inode = new_inode_pseudo(sock_mnt->mnt_sb); 5681da177e4SLinus Torvalds if (!inode) 5691da177e4SLinus Torvalds return NULL; 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds sock = SOCKET_I(inode); 5721da177e4SLinus Torvalds 57329a020d3SEric Dumazet kmemcheck_annotate_bitfield(sock, type); 57485fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 5751da177e4SLinus Torvalds inode->i_mode = S_IFSOCK | S_IRWXUGO; 5768192b0c4SDavid Howells inode->i_uid = current_fsuid(); 5778192b0c4SDavid Howells inode->i_gid = current_fsgid(); 578600e1779SMasatake YAMATO inode->i_op = &sockfs_inode_ops; 5791da177e4SLinus Torvalds 58019e8d69cSAlex Shi this_cpu_add(sockets_in_use, 1); 5811da177e4SLinus Torvalds return sock; 5821da177e4SLinus Torvalds } 583f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc); 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds /** 5861da177e4SLinus Torvalds * sock_release - close a socket 5871da177e4SLinus Torvalds * @sock: socket to close 5881da177e4SLinus Torvalds * 5891da177e4SLinus Torvalds * The socket is released from the protocol stack if it has a release 5901da177e4SLinus Torvalds * callback, and the inode is then released if the socket is bound to 5911da177e4SLinus Torvalds * an inode not a file. 5921da177e4SLinus Torvalds */ 5931da177e4SLinus Torvalds 5941da177e4SLinus Torvalds void sock_release(struct socket *sock) 5951da177e4SLinus Torvalds { 5961da177e4SLinus Torvalds if (sock->ops) { 5971da177e4SLinus Torvalds struct module *owner = sock->ops->owner; 5981da177e4SLinus Torvalds 5991da177e4SLinus Torvalds sock->ops->release(sock); 6001da177e4SLinus Torvalds sock->ops = NULL; 6011da177e4SLinus Torvalds module_put(owner); 6021da177e4SLinus Torvalds } 6031da177e4SLinus Torvalds 604eaefd110SEric Dumazet if (rcu_dereference_protected(sock->wq, 1)->fasync_list) 6053410f22eSYang Yingliang pr_err("%s: fasync list not empty!\n", __func__); 6061da177e4SLinus Torvalds 60719e8d69cSAlex Shi this_cpu_sub(sockets_in_use, 1); 6081da177e4SLinus Torvalds if (!sock->file) { 6091da177e4SLinus Torvalds iput(SOCK_INODE(sock)); 6101da177e4SLinus Torvalds return; 6111da177e4SLinus Torvalds } 6121da177e4SLinus Torvalds sock->file = NULL; 6131da177e4SLinus Torvalds } 614c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release); 6151da177e4SLinus Torvalds 616c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) 61720d49473SPatrick Ohly { 618140c55d4SEric Dumazet u8 flags = *tx_flags; 619140c55d4SEric Dumazet 620c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE) 621140c55d4SEric Dumazet flags |= SKBTX_HW_TSTAMP; 622140c55d4SEric Dumazet 623c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) 624140c55d4SEric Dumazet flags |= SKBTX_SW_TSTAMP; 625140c55d4SEric Dumazet 626c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SCHED) 627140c55d4SEric Dumazet flags |= SKBTX_SCHED_TSTAMP; 628140c55d4SEric Dumazet 629140c55d4SEric Dumazet *tx_flags = flags; 63020d49473SPatrick Ohly } 63167cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp); 63220d49473SPatrick Ohly 633d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) 6341da177e4SLinus Torvalds { 63501e97e65SAl Viro int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg)); 636d8725c86SAl Viro BUG_ON(ret == -EIOCBQUEUED); 637d8725c86SAl Viro return ret; 6381da177e4SLinus Torvalds } 6390cf00c6fSGu Zheng 640d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg) 6410cf00c6fSGu Zheng { 642d8725c86SAl Viro int err = security_socket_sendmsg(sock, msg, 64301e97e65SAl Viro msg_data_left(msg)); 6441b784140SYing Xue 645d8725c86SAl Viro return err ?: sock_sendmsg_nosec(sock, msg); 6460cf00c6fSGu Zheng } 647c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg); 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg, 6501da177e4SLinus Torvalds struct kvec *vec, size_t num, size_t size) 6511da177e4SLinus Torvalds { 6526aa24814SAl Viro iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size); 653d8725c86SAl Viro return sock_sendmsg(sock, msg); 6541da177e4SLinus Torvalds } 655c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg); 6561da177e4SLinus Torvalds 65792f37fd2SEric Dumazet /* 65892f37fd2SEric Dumazet * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) 65992f37fd2SEric Dumazet */ 66092f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 66192f37fd2SEric Dumazet struct sk_buff *skb) 66292f37fd2SEric Dumazet { 66320d49473SPatrick Ohly int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 664f24b9be5SWillem de Bruijn struct scm_timestamping tss; 66520d49473SPatrick Ohly int empty = 1; 66620d49473SPatrick Ohly struct skb_shared_hwtstamps *shhwtstamps = 66720d49473SPatrick Ohly skb_hwtstamps(skb); 66892f37fd2SEric Dumazet 66920d49473SPatrick Ohly /* Race occurred between timestamp enabling and packet 67020d49473SPatrick Ohly receiving. Fill in the current time for now. */ 67120d49473SPatrick Ohly if (need_software_tstamp && skb->tstamp.tv64 == 0) 67220d49473SPatrick Ohly __net_timestamp(skb); 67320d49473SPatrick Ohly 67420d49473SPatrick Ohly if (need_software_tstamp) { 67592f37fd2SEric Dumazet if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { 67692f37fd2SEric Dumazet struct timeval tv; 67720d49473SPatrick Ohly skb_get_timestamp(skb, &tv); 67820d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, 67920d49473SPatrick Ohly sizeof(tv), &tv); 68092f37fd2SEric Dumazet } else { 681f24b9be5SWillem de Bruijn struct timespec ts; 682f24b9be5SWillem de Bruijn skb_get_timestampns(skb, &ts); 68320d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, 684f24b9be5SWillem de Bruijn sizeof(ts), &ts); 68592f37fd2SEric Dumazet } 68692f37fd2SEric Dumazet } 68792f37fd2SEric Dumazet 688f24b9be5SWillem de Bruijn memset(&tss, 0, sizeof(tss)); 689c199105dSWillem de Bruijn if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && 690f24b9be5SWillem de Bruijn ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) 69120d49473SPatrick Ohly empty = 0; 6924d276eb6SWillem de Bruijn if (shhwtstamps && 693b9f40e21SWillem de Bruijn (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && 694f24b9be5SWillem de Bruijn ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) 69520d49473SPatrick Ohly empty = 0; 6961c885808SFrancis Yan if (!empty) { 69720d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, 698f24b9be5SWillem de Bruijn SCM_TIMESTAMPING, sizeof(tss), &tss); 6991c885808SFrancis Yan 7001c885808SFrancis Yan if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS)) 7011c885808SFrancis Yan put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, 7021c885808SFrancis Yan skb->len, skb->data); 7031c885808SFrancis Yan } 70420d49473SPatrick Ohly } 7057c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 7067c81fd8bSArnaldo Carvalho de Melo 7076e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, 7086e3e939fSJohannes Berg struct sk_buff *skb) 7096e3e939fSJohannes Berg { 7106e3e939fSJohannes Berg int ack; 7116e3e939fSJohannes Berg 7126e3e939fSJohannes Berg if (!sock_flag(sk, SOCK_WIFI_STATUS)) 7136e3e939fSJohannes Berg return; 7146e3e939fSJohannes Berg if (!skb->wifi_acked_valid) 7156e3e939fSJohannes Berg return; 7166e3e939fSJohannes Berg 7176e3e939fSJohannes Berg ack = skb->wifi_acked; 7186e3e939fSJohannes Berg 7196e3e939fSJohannes Berg put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack); 7206e3e939fSJohannes Berg } 7216e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status); 7226e3e939fSJohannes Berg 72311165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, 72411165f14Sstephen hemminger struct sk_buff *skb) 7253b885787SNeil Horman { 726744d5a3eSEyal Birger if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount) 7273b885787SNeil Horman put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, 728744d5a3eSEyal Birger sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount); 7293b885787SNeil Horman } 7303b885787SNeil Horman 731767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 7323b885787SNeil Horman struct sk_buff *skb) 7333b885787SNeil Horman { 7343b885787SNeil Horman sock_recv_timestamp(msg, sk, skb); 7353b885787SNeil Horman sock_recv_drops(msg, sk, skb); 7363b885787SNeil Horman } 737767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); 7383b885787SNeil Horman 7391b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, 7401b784140SYing Xue int flags) 741a2e27255SArnaldo Carvalho de Melo { 7422da62906SAl Viro return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags); 7432da62906SAl Viro } 744a2e27255SArnaldo Carvalho de Melo 7452da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags) 7462da62906SAl Viro { 7472da62906SAl Viro int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags); 7482da62906SAl Viro 7492da62906SAl Viro return err ?: sock_recvmsg_nosec(sock, msg, flags); 7501da177e4SLinus Torvalds } 751c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg); 7521da177e4SLinus Torvalds 753c1249c0aSMartin Lucina /** 754c1249c0aSMartin Lucina * kernel_recvmsg - Receive a message from a socket (kernel space) 755c1249c0aSMartin Lucina * @sock: The socket to receive the message from 756c1249c0aSMartin Lucina * @msg: Received message 757c1249c0aSMartin Lucina * @vec: Input s/g array for message data 758c1249c0aSMartin Lucina * @num: Size of input s/g array 759c1249c0aSMartin Lucina * @size: Number of bytes to read 760c1249c0aSMartin Lucina * @flags: Message flags (MSG_DONTWAIT, etc...) 761c1249c0aSMartin Lucina * 762c1249c0aSMartin Lucina * On return the msg structure contains the scatter/gather array passed in the 763c1249c0aSMartin Lucina * vec argument. The array is modified so that it consists of the unfilled 764c1249c0aSMartin Lucina * portion of the original array. 765c1249c0aSMartin Lucina * 766c1249c0aSMartin Lucina * The returned value is the total number of bytes received, or an error. 767c1249c0aSMartin Lucina */ 7681da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg, 76989bddce5SStephen Hemminger struct kvec *vec, size_t num, size_t size, int flags) 7701da177e4SLinus Torvalds { 7711da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 7721da177e4SLinus Torvalds int result; 7731da177e4SLinus Torvalds 7746aa24814SAl Viro iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size); 7751da177e4SLinus Torvalds set_fs(KERNEL_DS); 7762da62906SAl Viro result = sock_recvmsg(sock, msg, flags); 7771da177e4SLinus Torvalds set_fs(oldfs); 7781da177e4SLinus Torvalds return result; 7791da177e4SLinus Torvalds } 780c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg); 7811da177e4SLinus Torvalds 78220380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page, 7831da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more) 7841da177e4SLinus Torvalds { 7851da177e4SLinus Torvalds struct socket *sock; 7861da177e4SLinus Torvalds int flags; 7871da177e4SLinus Torvalds 788b69aee04SEric Dumazet sock = file->private_data; 7891da177e4SLinus Torvalds 79035f9c09fSEric Dumazet flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 79135f9c09fSEric Dumazet /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */ 79235f9c09fSEric Dumazet flags |= more; 7931da177e4SLinus Torvalds 794e6949583SLinus Torvalds return kernel_sendpage(sock, page, offset, size, flags); 7951da177e4SLinus Torvalds } 7961da177e4SLinus Torvalds 7979c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 7989c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 7999c55e01cSJens Axboe unsigned int flags) 8009c55e01cSJens Axboe { 8019c55e01cSJens Axboe struct socket *sock = file->private_data; 8029c55e01cSJens Axboe 803997b37daSRémi Denis-Courmont if (unlikely(!sock->ops->splice_read)) 804997b37daSRémi Denis-Courmont return -EINVAL; 805997b37daSRémi Denis-Courmont 8069c55e01cSJens Axboe return sock->ops->splice_read(sock, ppos, pipe, len, flags); 8079c55e01cSJens Axboe } 8089c55e01cSJens Axboe 8098ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to) 810ce1d4d3eSChristoph Hellwig { 8116d652330SAl Viro struct file *file = iocb->ki_filp; 8126d652330SAl Viro struct socket *sock = file->private_data; 8130345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *to, 8140345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 8158ae5e030SAl Viro ssize_t res; 816ce1d4d3eSChristoph Hellwig 8178ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 8188ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 8198ae5e030SAl Viro 8208ae5e030SAl Viro if (iocb->ki_pos != 0) 821ce1d4d3eSChristoph Hellwig return -ESPIPE; 822027445c3SBadari Pulavarty 82366ee59afSChristoph Hellwig if (!iov_iter_count(to)) /* Match SYS5 behaviour */ 824ce1d4d3eSChristoph Hellwig return 0; 825ce1d4d3eSChristoph Hellwig 8262da62906SAl Viro res = sock_recvmsg(sock, &msg, msg.msg_flags); 8278ae5e030SAl Viro *to = msg.msg_iter; 8288ae5e030SAl Viro return res; 829ce1d4d3eSChristoph Hellwig } 830ce1d4d3eSChristoph Hellwig 8318ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) 8321da177e4SLinus Torvalds { 8336d652330SAl Viro struct file *file = iocb->ki_filp; 8346d652330SAl Viro struct socket *sock = file->private_data; 8350345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *from, 8360345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 8378ae5e030SAl Viro ssize_t res; 8381da177e4SLinus Torvalds 8398ae5e030SAl Viro if (iocb->ki_pos != 0) 840ce1d4d3eSChristoph Hellwig return -ESPIPE; 841027445c3SBadari Pulavarty 8428ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 8438ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 8448ae5e030SAl Viro 8456d652330SAl Viro if (sock->type == SOCK_SEQPACKET) 8466d652330SAl Viro msg.msg_flags |= MSG_EOR; 8476d652330SAl Viro 848d8725c86SAl Viro res = sock_sendmsg(sock, &msg); 8498ae5e030SAl Viro *from = msg.msg_iter; 8508ae5e030SAl Viro return res; 8511da177e4SLinus Torvalds } 8521da177e4SLinus Torvalds 8531da177e4SLinus Torvalds /* 8541da177e4SLinus Torvalds * Atomic setting of ioctl hooks to avoid race 8551da177e4SLinus Torvalds * with module unload. 8561da177e4SLinus Torvalds */ 8571da177e4SLinus Torvalds 8584a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex); 859c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg); 8601da177e4SLinus Torvalds 861881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *)) 8621da177e4SLinus Torvalds { 8634a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 8641da177e4SLinus Torvalds br_ioctl_hook = hook; 8654a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 8661da177e4SLinus Torvalds } 8671da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set); 8681da177e4SLinus Torvalds 8694a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex); 870881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg); 8711da177e4SLinus Torvalds 872881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *)) 8731da177e4SLinus Torvalds { 8744a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 8751da177e4SLinus Torvalds vlan_ioctl_hook = hook; 8764a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 8771da177e4SLinus Torvalds } 8781da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set); 8791da177e4SLinus Torvalds 8804a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex); 8811da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *); 8821da177e4SLinus Torvalds 8831da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) 8841da177e4SLinus Torvalds { 8854a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 8861da177e4SLinus Torvalds dlci_ioctl_hook = hook; 8874a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 8881da177e4SLinus Torvalds } 8891da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set); 8901da177e4SLinus Torvalds 8916b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock, 8926b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 8936b96018bSArnd Bergmann { 8946b96018bSArnd Bergmann int err; 8956b96018bSArnd Bergmann void __user *argp = (void __user *)arg; 8966b96018bSArnd Bergmann 8976b96018bSArnd Bergmann err = sock->ops->ioctl(sock, cmd, arg); 8986b96018bSArnd Bergmann 8996b96018bSArnd Bergmann /* 9006b96018bSArnd Bergmann * If this ioctl is unknown try to hand it down 9016b96018bSArnd Bergmann * to the NIC driver. 9026b96018bSArnd Bergmann */ 9036b96018bSArnd Bergmann if (err == -ENOIOCTLCMD) 9046b96018bSArnd Bergmann err = dev_ioctl(net, cmd, argp); 9056b96018bSArnd Bergmann 9066b96018bSArnd Bergmann return err; 9076b96018bSArnd Bergmann } 9086b96018bSArnd Bergmann 9091da177e4SLinus Torvalds /* 9101da177e4SLinus Torvalds * With an ioctl, arg may well be a user mode pointer, but we don't know 9111da177e4SLinus Torvalds * what to do with it - that's up to the protocol still. 9121da177e4SLinus Torvalds */ 9131da177e4SLinus Torvalds 914c62cce2cSAndrey Vagin static struct ns_common *get_net_ns(struct ns_common *ns) 915c62cce2cSAndrey Vagin { 916c62cce2cSAndrey Vagin return &get_net(container_of(ns, struct net, ns))->ns; 917c62cce2cSAndrey Vagin } 918c62cce2cSAndrey Vagin 9191da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) 9201da177e4SLinus Torvalds { 9211da177e4SLinus Torvalds struct socket *sock; 922881d966bSEric W. Biederman struct sock *sk; 9231da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 9241da177e4SLinus Torvalds int pid, err; 925881d966bSEric W. Biederman struct net *net; 9261da177e4SLinus Torvalds 927b69aee04SEric Dumazet sock = file->private_data; 928881d966bSEric W. Biederman sk = sock->sk; 9293b1e0a65SYOSHIFUJI Hideaki net = sock_net(sk); 9301da177e4SLinus Torvalds if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { 931881d966bSEric W. Biederman err = dev_ioctl(net, cmd, argp); 9321da177e4SLinus Torvalds } else 9333d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE 9341da177e4SLinus Torvalds if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { 935881d966bSEric W. Biederman err = dev_ioctl(net, cmd, argp); 9361da177e4SLinus Torvalds } else 9373d23e349SJohannes Berg #endif 9381da177e4SLinus Torvalds switch (cmd) { 9391da177e4SLinus Torvalds case FIOSETOWN: 9401da177e4SLinus Torvalds case SIOCSPGRP: 9411da177e4SLinus Torvalds err = -EFAULT; 9421da177e4SLinus Torvalds if (get_user(pid, (int __user *)argp)) 9431da177e4SLinus Torvalds break; 944e0b93eddSJeff Layton f_setown(sock->file, pid, 1); 945e0b93eddSJeff Layton err = 0; 9461da177e4SLinus Torvalds break; 9471da177e4SLinus Torvalds case FIOGETOWN: 9481da177e4SLinus Torvalds case SIOCGPGRP: 949609d7fa9SEric W. Biederman err = put_user(f_getown(sock->file), 95089bddce5SStephen Hemminger (int __user *)argp); 9511da177e4SLinus Torvalds break; 9521da177e4SLinus Torvalds case SIOCGIFBR: 9531da177e4SLinus Torvalds case SIOCSIFBR: 9541da177e4SLinus Torvalds case SIOCBRADDBR: 9551da177e4SLinus Torvalds case SIOCBRDELBR: 9561da177e4SLinus Torvalds err = -ENOPKG; 9571da177e4SLinus Torvalds if (!br_ioctl_hook) 9581da177e4SLinus Torvalds request_module("bridge"); 9591da177e4SLinus Torvalds 9604a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 9611da177e4SLinus Torvalds if (br_ioctl_hook) 962881d966bSEric W. Biederman err = br_ioctl_hook(net, cmd, argp); 9634a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 9641da177e4SLinus Torvalds break; 9651da177e4SLinus Torvalds case SIOCGIFVLAN: 9661da177e4SLinus Torvalds case SIOCSIFVLAN: 9671da177e4SLinus Torvalds err = -ENOPKG; 9681da177e4SLinus Torvalds if (!vlan_ioctl_hook) 9691da177e4SLinus Torvalds request_module("8021q"); 9701da177e4SLinus Torvalds 9714a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 9721da177e4SLinus Torvalds if (vlan_ioctl_hook) 973881d966bSEric W. Biederman err = vlan_ioctl_hook(net, argp); 9744a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 9751da177e4SLinus Torvalds break; 9761da177e4SLinus Torvalds case SIOCADDDLCI: 9771da177e4SLinus Torvalds case SIOCDELDLCI: 9781da177e4SLinus Torvalds err = -ENOPKG; 9791da177e4SLinus Torvalds if (!dlci_ioctl_hook) 9801da177e4SLinus Torvalds request_module("dlci"); 9811da177e4SLinus Torvalds 9824a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 9837512cbf6SPavel Emelyanov if (dlci_ioctl_hook) 9841da177e4SLinus Torvalds err = dlci_ioctl_hook(cmd, argp); 9854a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 9861da177e4SLinus Torvalds break; 987c62cce2cSAndrey Vagin case SIOCGSKNS: 988c62cce2cSAndrey Vagin err = -EPERM; 989c62cce2cSAndrey Vagin if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 990c62cce2cSAndrey Vagin break; 991c62cce2cSAndrey Vagin 992c62cce2cSAndrey Vagin err = open_related_ns(&net->ns, get_net_ns); 993c62cce2cSAndrey Vagin break; 9941da177e4SLinus Torvalds default: 9956b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, arg); 9961da177e4SLinus Torvalds break; 9971da177e4SLinus Torvalds } 9981da177e4SLinus Torvalds return err; 9991da177e4SLinus Torvalds } 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res) 10021da177e4SLinus Torvalds { 10031da177e4SLinus Torvalds int err; 10041da177e4SLinus Torvalds struct socket *sock = NULL; 10051da177e4SLinus Torvalds 10061da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, 1); 10071da177e4SLinus Torvalds if (err) 10081da177e4SLinus Torvalds goto out; 10091da177e4SLinus Torvalds 10101da177e4SLinus Torvalds sock = sock_alloc(); 10111da177e4SLinus Torvalds if (!sock) { 10121da177e4SLinus Torvalds err = -ENOMEM; 10131da177e4SLinus Torvalds goto out; 10141da177e4SLinus Torvalds } 10151da177e4SLinus Torvalds 10161da177e4SLinus Torvalds sock->type = type; 10177420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, 1); 10187420ed23SVenkat Yekkirala if (err) 10197420ed23SVenkat Yekkirala goto out_release; 10207420ed23SVenkat Yekkirala 10211da177e4SLinus Torvalds out: 10221da177e4SLinus Torvalds *res = sock; 10231da177e4SLinus Torvalds return err; 10247420ed23SVenkat Yekkirala out_release: 10257420ed23SVenkat Yekkirala sock_release(sock); 10267420ed23SVenkat Yekkirala sock = NULL; 10277420ed23SVenkat Yekkirala goto out; 10281da177e4SLinus Torvalds } 1029c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite); 10301da177e4SLinus Torvalds 10311da177e4SLinus Torvalds /* No kernel lock held - perfect */ 10321da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait) 10331da177e4SLinus Torvalds { 1034cbf55001SEliezer Tamir unsigned int busy_flag = 0; 10351da177e4SLinus Torvalds struct socket *sock; 10361da177e4SLinus Torvalds 10371da177e4SLinus Torvalds /* 10381da177e4SLinus Torvalds * We can't return errors to poll, so it's either yes or no. 10391da177e4SLinus Torvalds */ 1040b69aee04SEric Dumazet sock = file->private_data; 10412d48d67fSEliezer Tamir 1042cbf55001SEliezer Tamir if (sk_can_busy_loop(sock->sk)) { 10432d48d67fSEliezer Tamir /* this socket can poll_ll so tell the system call */ 1044cbf55001SEliezer Tamir busy_flag = POLL_BUSY_LOOP; 10452d48d67fSEliezer Tamir 10462d48d67fSEliezer Tamir /* once, only if requested by syscall */ 1047cbf55001SEliezer Tamir if (wait && (wait->_key & POLL_BUSY_LOOP)) 1048cbf55001SEliezer Tamir sk_busy_loop(sock->sk, 1); 10492d48d67fSEliezer Tamir } 10502d48d67fSEliezer Tamir 1051cbf55001SEliezer Tamir return busy_flag | sock->ops->poll(file, sock, wait); 10521da177e4SLinus Torvalds } 10531da177e4SLinus Torvalds 10541da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma) 10551da177e4SLinus Torvalds { 1056b69aee04SEric Dumazet struct socket *sock = file->private_data; 10571da177e4SLinus Torvalds 10581da177e4SLinus Torvalds return sock->ops->mmap(file, sock, vma); 10591da177e4SLinus Torvalds } 10601da177e4SLinus Torvalds 106120380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp) 10621da177e4SLinus Torvalds { 10631da177e4SLinus Torvalds sock_release(SOCKET_I(inode)); 10641da177e4SLinus Torvalds return 0; 10651da177e4SLinus Torvalds } 10661da177e4SLinus Torvalds 10671da177e4SLinus Torvalds /* 10681da177e4SLinus Torvalds * Update the socket async list 10691da177e4SLinus Torvalds * 10701da177e4SLinus Torvalds * Fasync_list locking strategy. 10711da177e4SLinus Torvalds * 10721da177e4SLinus Torvalds * 1. fasync_list is modified only under process context socket lock 10731da177e4SLinus Torvalds * i.e. under semaphore. 10741da177e4SLinus Torvalds * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1075989a2979SEric Dumazet * or under socket lock 10761da177e4SLinus Torvalds */ 10771da177e4SLinus Torvalds 10781da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on) 10791da177e4SLinus Torvalds { 1080989a2979SEric Dumazet struct socket *sock = filp->private_data; 1081989a2979SEric Dumazet struct sock *sk = sock->sk; 1082eaefd110SEric Dumazet struct socket_wq *wq; 10831da177e4SLinus Torvalds 1084989a2979SEric Dumazet if (sk == NULL) 10851da177e4SLinus Torvalds return -EINVAL; 10861da177e4SLinus Torvalds 10871da177e4SLinus Torvalds lock_sock(sk); 10881e1d04e6SHannes Frederic Sowa wq = rcu_dereference_protected(sock->wq, lockdep_sock_is_held(sk)); 1089eaefd110SEric Dumazet fasync_helper(fd, filp, on, &wq->fasync_list); 10901da177e4SLinus Torvalds 1091eaefd110SEric Dumazet if (!wq->fasync_list) 1092bcdce719SEric Dumazet sock_reset_flag(sk, SOCK_FASYNC); 1093989a2979SEric Dumazet else 1094989a2979SEric Dumazet sock_set_flag(sk, SOCK_FASYNC); 10951da177e4SLinus Torvalds 1096989a2979SEric Dumazet release_sock(sk); 10971da177e4SLinus Torvalds return 0; 10981da177e4SLinus Torvalds } 10991da177e4SLinus Torvalds 1100ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */ 11011da177e4SLinus Torvalds 1102ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band) 11031da177e4SLinus Torvalds { 1104ceb5d58bSEric Dumazet if (!wq || !wq->fasync_list) 1105ceb5d58bSEric Dumazet return -1; 110643815482SEric Dumazet 110789bddce5SStephen Hemminger switch (how) { 11088d8ad9d7SPavel Emelyanov case SOCK_WAKE_WAITD: 1109ceb5d58bSEric Dumazet if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags)) 11101da177e4SLinus Torvalds break; 11111da177e4SLinus Torvalds goto call_kill; 11128d8ad9d7SPavel Emelyanov case SOCK_WAKE_SPACE: 1113ceb5d58bSEric Dumazet if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags)) 11141da177e4SLinus Torvalds break; 11151da177e4SLinus Torvalds /* fall through */ 11168d8ad9d7SPavel Emelyanov case SOCK_WAKE_IO: 11171da177e4SLinus Torvalds call_kill: 111843815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGIO, band); 11191da177e4SLinus Torvalds break; 11208d8ad9d7SPavel Emelyanov case SOCK_WAKE_URG: 112143815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGURG, band); 11221da177e4SLinus Torvalds } 1123ceb5d58bSEric Dumazet 11241da177e4SLinus Torvalds return 0; 11251da177e4SLinus Torvalds } 1126c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async); 11271da177e4SLinus Torvalds 1128721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol, 112989bddce5SStephen Hemminger struct socket **res, int kern) 11301da177e4SLinus Torvalds { 11311da177e4SLinus Torvalds int err; 11321da177e4SLinus Torvalds struct socket *sock; 113355737fdaSStephen Hemminger const struct net_proto_family *pf; 11341da177e4SLinus Torvalds 11351da177e4SLinus Torvalds /* 11361da177e4SLinus Torvalds * Check protocol is in range 11371da177e4SLinus Torvalds */ 11381da177e4SLinus Torvalds if (family < 0 || family >= NPROTO) 11391da177e4SLinus Torvalds return -EAFNOSUPPORT; 11401da177e4SLinus Torvalds if (type < 0 || type >= SOCK_MAX) 11411da177e4SLinus Torvalds return -EINVAL; 11421da177e4SLinus Torvalds 11431da177e4SLinus Torvalds /* Compatibility. 11441da177e4SLinus Torvalds 11451da177e4SLinus Torvalds This uglymoron is moved from INET layer to here to avoid 11461da177e4SLinus Torvalds deadlock in module load. 11471da177e4SLinus Torvalds */ 11481da177e4SLinus Torvalds if (family == PF_INET && type == SOCK_PACKET) { 1149f3c98690Sliping.zhang pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n", 115089bddce5SStephen Hemminger current->comm); 11511da177e4SLinus Torvalds family = PF_PACKET; 11521da177e4SLinus Torvalds } 11531da177e4SLinus Torvalds 11541da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, kern); 11551da177e4SLinus Torvalds if (err) 11561da177e4SLinus Torvalds return err; 11571da177e4SLinus Torvalds 115855737fdaSStephen Hemminger /* 115955737fdaSStephen Hemminger * Allocate the socket and allow the family to set things up. if 116055737fdaSStephen Hemminger * the protocol is 0, the family is instructed to select an appropriate 116155737fdaSStephen Hemminger * default. 116255737fdaSStephen Hemminger */ 116355737fdaSStephen Hemminger sock = sock_alloc(); 116455737fdaSStephen Hemminger if (!sock) { 1165e87cc472SJoe Perches net_warn_ratelimited("socket: no more sockets\n"); 116655737fdaSStephen Hemminger return -ENFILE; /* Not exactly a match, but its the 116755737fdaSStephen Hemminger closest posix thing */ 116855737fdaSStephen Hemminger } 116955737fdaSStephen Hemminger 117055737fdaSStephen Hemminger sock->type = type; 117155737fdaSStephen Hemminger 117295a5afcaSJohannes Berg #ifdef CONFIG_MODULES 11731da177e4SLinus Torvalds /* Attempt to load a protocol module if the find failed. 11741da177e4SLinus Torvalds * 11751da177e4SLinus Torvalds * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user 11761da177e4SLinus Torvalds * requested real, full-featured networking support upon configuration. 11771da177e4SLinus Torvalds * Otherwise module support will break! 11781da177e4SLinus Torvalds */ 1179190683a9SEric Dumazet if (rcu_access_pointer(net_families[family]) == NULL) 11801da177e4SLinus Torvalds request_module("net-pf-%d", family); 11811da177e4SLinus Torvalds #endif 11821da177e4SLinus Torvalds 118355737fdaSStephen Hemminger rcu_read_lock(); 118455737fdaSStephen Hemminger pf = rcu_dereference(net_families[family]); 11851da177e4SLinus Torvalds err = -EAFNOSUPPORT; 118655737fdaSStephen Hemminger if (!pf) 118755737fdaSStephen Hemminger goto out_release; 11881da177e4SLinus Torvalds 11891da177e4SLinus Torvalds /* 11901da177e4SLinus Torvalds * We will call the ->create function, that possibly is in a loadable 11911da177e4SLinus Torvalds * module, so we have to bump that loadable module refcnt first. 11921da177e4SLinus Torvalds */ 119355737fdaSStephen Hemminger if (!try_module_get(pf->owner)) 11941da177e4SLinus Torvalds goto out_release; 11951da177e4SLinus Torvalds 119655737fdaSStephen Hemminger /* Now protected by module ref count */ 119755737fdaSStephen Hemminger rcu_read_unlock(); 119855737fdaSStephen Hemminger 11993f378b68SEric Paris err = pf->create(net, sock, protocol, kern); 120055737fdaSStephen Hemminger if (err < 0) 12011da177e4SLinus Torvalds goto out_module_put; 1202a79af59eSFrank Filz 12031da177e4SLinus Torvalds /* 12041da177e4SLinus Torvalds * Now to bump the refcnt of the [loadable] module that owns this 12051da177e4SLinus Torvalds * socket at sock_release time we decrement its refcnt. 12061da177e4SLinus Torvalds */ 120755737fdaSStephen Hemminger if (!try_module_get(sock->ops->owner)) 120855737fdaSStephen Hemminger goto out_module_busy; 120955737fdaSStephen Hemminger 12101da177e4SLinus Torvalds /* 12111da177e4SLinus Torvalds * Now that we're done with the ->create function, the [loadable] 12121da177e4SLinus Torvalds * module can have its refcnt decremented 12131da177e4SLinus Torvalds */ 121455737fdaSStephen Hemminger module_put(pf->owner); 12157420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, kern); 12167420ed23SVenkat Yekkirala if (err) 12173b185525SHerbert Xu goto out_sock_release; 121855737fdaSStephen Hemminger *res = sock; 12191da177e4SLinus Torvalds 122055737fdaSStephen Hemminger return 0; 122155737fdaSStephen Hemminger 122255737fdaSStephen Hemminger out_module_busy: 122355737fdaSStephen Hemminger err = -EAFNOSUPPORT; 12241da177e4SLinus Torvalds out_module_put: 122555737fdaSStephen Hemminger sock->ops = NULL; 122655737fdaSStephen Hemminger module_put(pf->owner); 122755737fdaSStephen Hemminger out_sock_release: 12281da177e4SLinus Torvalds sock_release(sock); 122955737fdaSStephen Hemminger return err; 123055737fdaSStephen Hemminger 123155737fdaSStephen Hemminger out_release: 123255737fdaSStephen Hemminger rcu_read_unlock(); 123355737fdaSStephen Hemminger goto out_sock_release; 12341da177e4SLinus Torvalds } 1235721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create); 12361da177e4SLinus Torvalds 12371da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res) 12381da177e4SLinus Torvalds { 12391b8d7ae4SEric W. Biederman return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); 12401da177e4SLinus Torvalds } 1241c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create); 12421da177e4SLinus Torvalds 1243eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res) 12441da177e4SLinus Torvalds { 1245eeb1bd5cSEric W. Biederman return __sock_create(net, family, type, protocol, res, 1); 12461da177e4SLinus Torvalds } 1247c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern); 12481da177e4SLinus Torvalds 12493e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) 12501da177e4SLinus Torvalds { 12511da177e4SLinus Torvalds int retval; 12521da177e4SLinus Torvalds struct socket *sock; 1253a677a039SUlrich Drepper int flags; 1254a677a039SUlrich Drepper 1255e38b36f3SUlrich Drepper /* Check the SOCK_* constants for consistency. */ 1256e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); 1257e38b36f3SUlrich Drepper BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); 1258e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); 1259e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); 1260e38b36f3SUlrich Drepper 1261a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 126277d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1263a677a039SUlrich Drepper return -EINVAL; 1264a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 12651da177e4SLinus Torvalds 1266aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1267aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1268aaca0bdcSUlrich Drepper 12691da177e4SLinus Torvalds retval = sock_create(family, type, protocol, &sock); 12701da177e4SLinus Torvalds if (retval < 0) 12711da177e4SLinus Torvalds goto out; 12721da177e4SLinus Torvalds 127377d27200SUlrich Drepper retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); 12741da177e4SLinus Torvalds if (retval < 0) 12751da177e4SLinus Torvalds goto out_release; 12761da177e4SLinus Torvalds 12771da177e4SLinus Torvalds out: 12781da177e4SLinus Torvalds /* It may be already another descriptor 8) Not kernel problem. */ 12791da177e4SLinus Torvalds return retval; 12801da177e4SLinus Torvalds 12811da177e4SLinus Torvalds out_release: 12821da177e4SLinus Torvalds sock_release(sock); 12831da177e4SLinus Torvalds return retval; 12841da177e4SLinus Torvalds } 12851da177e4SLinus Torvalds 12861da177e4SLinus Torvalds /* 12871da177e4SLinus Torvalds * Create a pair of connected sockets. 12881da177e4SLinus Torvalds */ 12891da177e4SLinus Torvalds 12903e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, 12913e0fa65fSHeiko Carstens int __user *, usockvec) 12921da177e4SLinus Torvalds { 12931da177e4SLinus Torvalds struct socket *sock1, *sock2; 12941da177e4SLinus Torvalds int fd1, fd2, err; 1295db349509SAl Viro struct file *newfile1, *newfile2; 1296a677a039SUlrich Drepper int flags; 1297a677a039SUlrich Drepper 1298a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 129977d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1300a677a039SUlrich Drepper return -EINVAL; 1301a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13021da177e4SLinus Torvalds 1303aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1304aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1305aaca0bdcSUlrich Drepper 13061da177e4SLinus Torvalds /* 13071da177e4SLinus Torvalds * Obtain the first socket and check if the underlying protocol 13081da177e4SLinus Torvalds * supports the socketpair call. 13091da177e4SLinus Torvalds */ 13101da177e4SLinus Torvalds 13111da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock1); 13121da177e4SLinus Torvalds if (err < 0) 13131da177e4SLinus Torvalds goto out; 13141da177e4SLinus Torvalds 13151da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock2); 13161da177e4SLinus Torvalds if (err < 0) 13171da177e4SLinus Torvalds goto out_release_1; 13181da177e4SLinus Torvalds 13191da177e4SLinus Torvalds err = sock1->ops->socketpair(sock1, sock2); 13201da177e4SLinus Torvalds if (err < 0) 13211da177e4SLinus Torvalds goto out_release_both; 13221da177e4SLinus Torvalds 132328407630SAl Viro fd1 = get_unused_fd_flags(flags); 1324bf3c23d1SDavid S. Miller if (unlikely(fd1 < 0)) { 1325bf3c23d1SDavid S. Miller err = fd1; 13261da177e4SLinus Torvalds goto out_release_both; 1327bf3c23d1SDavid S. Miller } 1328d73aa286SYann Droneaud 132928407630SAl Viro fd2 = get_unused_fd_flags(flags); 1330198de4d7SAl Viro if (unlikely(fd2 < 0)) { 1331198de4d7SAl Viro err = fd2; 1332d73aa286SYann Droneaud goto out_put_unused_1; 133328407630SAl Viro } 133428407630SAl Viro 1335aab174f0SLinus Torvalds newfile1 = sock_alloc_file(sock1, flags, NULL); 1336b5ffe634SViresh Kumar if (IS_ERR(newfile1)) { 133728407630SAl Viro err = PTR_ERR(newfile1); 1338d73aa286SYann Droneaud goto out_put_unused_both; 133928407630SAl Viro } 134028407630SAl Viro 1341aab174f0SLinus Torvalds newfile2 = sock_alloc_file(sock2, flags, NULL); 134228407630SAl Viro if (IS_ERR(newfile2)) { 134328407630SAl Viro err = PTR_ERR(newfile2); 1344d73aa286SYann Droneaud goto out_fput_1; 1345db349509SAl Viro } 1346db349509SAl Viro 1347d73aa286SYann Droneaud err = put_user(fd1, &usockvec[0]); 1348d73aa286SYann Droneaud if (err) 1349d73aa286SYann Droneaud goto out_fput_both; 1350d73aa286SYann Droneaud 1351d73aa286SYann Droneaud err = put_user(fd2, &usockvec[1]); 1352d73aa286SYann Droneaud if (err) 1353d73aa286SYann Droneaud goto out_fput_both; 1354d73aa286SYann Droneaud 1355157cf649SAl Viro audit_fd_pair(fd1, fd2); 1356d73aa286SYann Droneaud 1357db349509SAl Viro fd_install(fd1, newfile1); 1358db349509SAl Viro fd_install(fd2, newfile2); 13591da177e4SLinus Torvalds /* fd1 and fd2 may be already another descriptors. 13601da177e4SLinus Torvalds * Not kernel problem. 13611da177e4SLinus Torvalds */ 13621da177e4SLinus Torvalds 13631da177e4SLinus Torvalds return 0; 13641da177e4SLinus Torvalds 1365d73aa286SYann Droneaud out_fput_both: 1366d73aa286SYann Droneaud fput(newfile2); 1367d73aa286SYann Droneaud fput(newfile1); 1368d73aa286SYann Droneaud put_unused_fd(fd2); 1369d73aa286SYann Droneaud put_unused_fd(fd1); 1370d73aa286SYann Droneaud goto out; 13711da177e4SLinus Torvalds 1372d73aa286SYann Droneaud out_fput_1: 1373d73aa286SYann Droneaud fput(newfile1); 1374d73aa286SYann Droneaud put_unused_fd(fd2); 1375d73aa286SYann Droneaud put_unused_fd(fd1); 1376d73aa286SYann Droneaud sock_release(sock2); 1377d73aa286SYann Droneaud goto out; 1378d73aa286SYann Droneaud 1379d73aa286SYann Droneaud out_put_unused_both: 1380d73aa286SYann Droneaud put_unused_fd(fd2); 1381d73aa286SYann Droneaud out_put_unused_1: 1382d73aa286SYann Droneaud put_unused_fd(fd1); 13831da177e4SLinus Torvalds out_release_both: 13841da177e4SLinus Torvalds sock_release(sock2); 13851da177e4SLinus Torvalds out_release_1: 13861da177e4SLinus Torvalds sock_release(sock1); 13871da177e4SLinus Torvalds out: 13881da177e4SLinus Torvalds return err; 13891da177e4SLinus Torvalds } 13901da177e4SLinus Torvalds 13911da177e4SLinus Torvalds /* 13921da177e4SLinus Torvalds * Bind a name to a socket. Nothing much to do here since it's 13931da177e4SLinus Torvalds * the protocol's responsibility to handle the local address. 13941da177e4SLinus Torvalds * 13951da177e4SLinus Torvalds * We move the socket address to kernel space before we call 13961da177e4SLinus Torvalds * the protocol layer (having also checked the address is ok). 13971da177e4SLinus Torvalds */ 13981da177e4SLinus Torvalds 139920f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) 14001da177e4SLinus Torvalds { 14011da177e4SLinus Torvalds struct socket *sock; 1402230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 14036cb153caSBenjamin LaHaise int err, fput_needed; 14041da177e4SLinus Torvalds 140589bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 140689bddce5SStephen Hemminger if (sock) { 140743db362dSMaciej Żenczykowski err = move_addr_to_kernel(umyaddr, addrlen, &address); 140889bddce5SStephen Hemminger if (err >= 0) { 140989bddce5SStephen Hemminger err = security_socket_bind(sock, 1410230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 141189bddce5SStephen Hemminger addrlen); 14126cb153caSBenjamin LaHaise if (!err) 14136cb153caSBenjamin LaHaise err = sock->ops->bind(sock, 141489bddce5SStephen Hemminger (struct sockaddr *) 1415230b1839SYOSHIFUJI Hideaki &address, addrlen); 14161da177e4SLinus Torvalds } 14176cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 14181da177e4SLinus Torvalds } 14191da177e4SLinus Torvalds return err; 14201da177e4SLinus Torvalds } 14211da177e4SLinus Torvalds 14221da177e4SLinus Torvalds /* 14231da177e4SLinus Torvalds * Perform a listen. Basically, we allow the protocol to do anything 14241da177e4SLinus Torvalds * necessary for a listen, and if that works, we mark the socket as 14251da177e4SLinus Torvalds * ready for listening. 14261da177e4SLinus Torvalds */ 14271da177e4SLinus Torvalds 14283e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog) 14291da177e4SLinus Torvalds { 14301da177e4SLinus Torvalds struct socket *sock; 14316cb153caSBenjamin LaHaise int err, fput_needed; 1432b8e1f9b5SPavel Emelyanov int somaxconn; 14331da177e4SLinus Torvalds 143489bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 143589bddce5SStephen Hemminger if (sock) { 14368efa6e93SPavel Emelyanov somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 143795c96174SEric Dumazet if ((unsigned int)backlog > somaxconn) 1438b8e1f9b5SPavel Emelyanov backlog = somaxconn; 14391da177e4SLinus Torvalds 14401da177e4SLinus Torvalds err = security_socket_listen(sock, backlog); 14416cb153caSBenjamin LaHaise if (!err) 14421da177e4SLinus Torvalds err = sock->ops->listen(sock, backlog); 14436cb153caSBenjamin LaHaise 14446cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 14451da177e4SLinus Torvalds } 14461da177e4SLinus Torvalds return err; 14471da177e4SLinus Torvalds } 14481da177e4SLinus Torvalds 14491da177e4SLinus Torvalds /* 14501da177e4SLinus Torvalds * For accept, we attempt to create a new socket, set up the link 14511da177e4SLinus Torvalds * with the client, wake up the client, then return the new 14521da177e4SLinus Torvalds * connected fd. We collect the address of the connector in kernel 14531da177e4SLinus Torvalds * space and move it to user at the very end. This is unclean because 14541da177e4SLinus Torvalds * we open the socket then return an error. 14551da177e4SLinus Torvalds * 14561da177e4SLinus Torvalds * 1003.1g adds the ability to recvmsg() to query connection pending 14571da177e4SLinus Torvalds * status to recvmsg. We need to add that support in a way thats 14581da177e4SLinus Torvalds * clean when we restucture accept also. 14591da177e4SLinus Torvalds */ 14601da177e4SLinus Torvalds 146120f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, 146220f37034SHeiko Carstens int __user *, upeer_addrlen, int, flags) 14631da177e4SLinus Torvalds { 14641da177e4SLinus Torvalds struct socket *sock, *newsock; 146539d8c1b6SDavid S. Miller struct file *newfile; 14666cb153caSBenjamin LaHaise int err, len, newfd, fput_needed; 1467230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 14681da177e4SLinus Torvalds 146977d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1470aaca0bdcSUlrich Drepper return -EINVAL; 1471aaca0bdcSUlrich Drepper 1472aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1473aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1474aaca0bdcSUlrich Drepper 14756cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 14761da177e4SLinus Torvalds if (!sock) 14771da177e4SLinus Torvalds goto out; 14781da177e4SLinus Torvalds 14791da177e4SLinus Torvalds err = -ENFILE; 1480c6d409cfSEric Dumazet newsock = sock_alloc(); 1481c6d409cfSEric Dumazet if (!newsock) 14821da177e4SLinus Torvalds goto out_put; 14831da177e4SLinus Torvalds 14841da177e4SLinus Torvalds newsock->type = sock->type; 14851da177e4SLinus Torvalds newsock->ops = sock->ops; 14861da177e4SLinus Torvalds 14871da177e4SLinus Torvalds /* 14881da177e4SLinus Torvalds * We don't need try_module_get here, as the listening socket (sock) 14891da177e4SLinus Torvalds * has the protocol module (sock->ops->owner) held. 14901da177e4SLinus Torvalds */ 14911da177e4SLinus Torvalds __module_get(newsock->ops->owner); 14921da177e4SLinus Torvalds 149328407630SAl Viro newfd = get_unused_fd_flags(flags); 149439d8c1b6SDavid S. Miller if (unlikely(newfd < 0)) { 149539d8c1b6SDavid S. Miller err = newfd; 14969a1875e6SDavid S. Miller sock_release(newsock); 14979a1875e6SDavid S. Miller goto out_put; 149839d8c1b6SDavid S. Miller } 1499aab174f0SLinus Torvalds newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); 1500b5ffe634SViresh Kumar if (IS_ERR(newfile)) { 150128407630SAl Viro err = PTR_ERR(newfile); 150228407630SAl Viro put_unused_fd(newfd); 150328407630SAl Viro sock_release(newsock); 150428407630SAl Viro goto out_put; 150528407630SAl Viro } 150639d8c1b6SDavid S. Miller 1507a79af59eSFrank Filz err = security_socket_accept(sock, newsock); 1508a79af59eSFrank Filz if (err) 150939d8c1b6SDavid S. Miller goto out_fd; 1510a79af59eSFrank Filz 15111da177e4SLinus Torvalds err = sock->ops->accept(sock, newsock, sock->file->f_flags); 15121da177e4SLinus Torvalds if (err < 0) 151339d8c1b6SDavid S. Miller goto out_fd; 15141da177e4SLinus Torvalds 15151da177e4SLinus Torvalds if (upeer_sockaddr) { 1516230b1839SYOSHIFUJI Hideaki if (newsock->ops->getname(newsock, (struct sockaddr *)&address, 151789bddce5SStephen Hemminger &len, 2) < 0) { 15181da177e4SLinus Torvalds err = -ECONNABORTED; 151939d8c1b6SDavid S. Miller goto out_fd; 15201da177e4SLinus Torvalds } 152143db362dSMaciej Żenczykowski err = move_addr_to_user(&address, 1522230b1839SYOSHIFUJI Hideaki len, upeer_sockaddr, upeer_addrlen); 15231da177e4SLinus Torvalds if (err < 0) 152439d8c1b6SDavid S. Miller goto out_fd; 15251da177e4SLinus Torvalds } 15261da177e4SLinus Torvalds 15271da177e4SLinus Torvalds /* File flags are not inherited via accept() unlike another OSes. */ 15281da177e4SLinus Torvalds 152939d8c1b6SDavid S. Miller fd_install(newfd, newfile); 153039d8c1b6SDavid S. Miller err = newfd; 15311da177e4SLinus Torvalds 15321da177e4SLinus Torvalds out_put: 15336cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 15341da177e4SLinus Torvalds out: 15351da177e4SLinus Torvalds return err; 153639d8c1b6SDavid S. Miller out_fd: 15379606a216SDavid S. Miller fput(newfile); 153839d8c1b6SDavid S. Miller put_unused_fd(newfd); 15391da177e4SLinus Torvalds goto out_put; 15401da177e4SLinus Torvalds } 15411da177e4SLinus Torvalds 154220f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, 154320f37034SHeiko Carstens int __user *, upeer_addrlen) 1544aaca0bdcSUlrich Drepper { 1545de11defeSUlrich Drepper return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); 1546aaca0bdcSUlrich Drepper } 1547aaca0bdcSUlrich Drepper 15481da177e4SLinus Torvalds /* 15491da177e4SLinus Torvalds * Attempt to connect to a socket with the server address. The address 15501da177e4SLinus Torvalds * is in user space so we verify it is OK and move it to kernel space. 15511da177e4SLinus Torvalds * 15521da177e4SLinus Torvalds * For 1003.1g we need to add clean support for a bind to AF_UNSPEC to 15531da177e4SLinus Torvalds * break bindings 15541da177e4SLinus Torvalds * 15551da177e4SLinus Torvalds * NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and 15561da177e4SLinus Torvalds * other SEQPACKET protocols that take time to connect() as it doesn't 15571da177e4SLinus Torvalds * include the -EINPROGRESS status for such sockets. 15581da177e4SLinus Torvalds */ 15591da177e4SLinus Torvalds 156020f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, 156120f37034SHeiko Carstens int, addrlen) 15621da177e4SLinus Torvalds { 15631da177e4SLinus Torvalds struct socket *sock; 1564230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 15656cb153caSBenjamin LaHaise int err, fput_needed; 15661da177e4SLinus Torvalds 15676cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 15681da177e4SLinus Torvalds if (!sock) 15691da177e4SLinus Torvalds goto out; 157043db362dSMaciej Żenczykowski err = move_addr_to_kernel(uservaddr, addrlen, &address); 15711da177e4SLinus Torvalds if (err < 0) 15721da177e4SLinus Torvalds goto out_put; 15731da177e4SLinus Torvalds 157489bddce5SStephen Hemminger err = 1575230b1839SYOSHIFUJI Hideaki security_socket_connect(sock, (struct sockaddr *)&address, addrlen); 15761da177e4SLinus Torvalds if (err) 15771da177e4SLinus Torvalds goto out_put; 15781da177e4SLinus Torvalds 1579230b1839SYOSHIFUJI Hideaki err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, 15801da177e4SLinus Torvalds sock->file->f_flags); 15811da177e4SLinus Torvalds out_put: 15826cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 15831da177e4SLinus Torvalds out: 15841da177e4SLinus Torvalds return err; 15851da177e4SLinus Torvalds } 15861da177e4SLinus Torvalds 15871da177e4SLinus Torvalds /* 15881da177e4SLinus Torvalds * Get the local address ('name') of a socket object. Move the obtained 15891da177e4SLinus Torvalds * name to user space. 15901da177e4SLinus Torvalds */ 15911da177e4SLinus Torvalds 159220f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr, 159320f37034SHeiko Carstens int __user *, usockaddr_len) 15941da177e4SLinus Torvalds { 15951da177e4SLinus Torvalds struct socket *sock; 1596230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 15976cb153caSBenjamin LaHaise int len, err, fput_needed; 15981da177e4SLinus Torvalds 15996cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16001da177e4SLinus Torvalds if (!sock) 16011da177e4SLinus Torvalds goto out; 16021da177e4SLinus Torvalds 16031da177e4SLinus Torvalds err = security_socket_getsockname(sock); 16041da177e4SLinus Torvalds if (err) 16051da177e4SLinus Torvalds goto out_put; 16061da177e4SLinus Torvalds 1607230b1839SYOSHIFUJI Hideaki err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0); 16081da177e4SLinus Torvalds if (err) 16091da177e4SLinus Torvalds goto out_put; 161043db362dSMaciej Żenczykowski err = move_addr_to_user(&address, len, usockaddr, usockaddr_len); 16111da177e4SLinus Torvalds 16121da177e4SLinus Torvalds out_put: 16136cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16141da177e4SLinus Torvalds out: 16151da177e4SLinus Torvalds return err; 16161da177e4SLinus Torvalds } 16171da177e4SLinus Torvalds 16181da177e4SLinus Torvalds /* 16191da177e4SLinus Torvalds * Get the remote address ('name') of a socket object. Move the obtained 16201da177e4SLinus Torvalds * name to user space. 16211da177e4SLinus Torvalds */ 16221da177e4SLinus Torvalds 162320f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, 162420f37034SHeiko Carstens int __user *, usockaddr_len) 16251da177e4SLinus Torvalds { 16261da177e4SLinus Torvalds struct socket *sock; 1627230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16286cb153caSBenjamin LaHaise int len, err, fput_needed; 16291da177e4SLinus Torvalds 163089bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 163189bddce5SStephen Hemminger if (sock != NULL) { 16321da177e4SLinus Torvalds err = security_socket_getpeername(sock); 16331da177e4SLinus Torvalds if (err) { 16346cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16351da177e4SLinus Torvalds return err; 16361da177e4SLinus Torvalds } 16371da177e4SLinus Torvalds 163889bddce5SStephen Hemminger err = 1639230b1839SYOSHIFUJI Hideaki sock->ops->getname(sock, (struct sockaddr *)&address, &len, 164089bddce5SStephen Hemminger 1); 16411da177e4SLinus Torvalds if (!err) 164243db362dSMaciej Żenczykowski err = move_addr_to_user(&address, len, usockaddr, 164389bddce5SStephen Hemminger usockaddr_len); 16446cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16451da177e4SLinus Torvalds } 16461da177e4SLinus Torvalds return err; 16471da177e4SLinus Torvalds } 16481da177e4SLinus Torvalds 16491da177e4SLinus Torvalds /* 16501da177e4SLinus Torvalds * Send a datagram to a given address. We move the address into kernel 16511da177e4SLinus Torvalds * space and check the user space data area is readable before invoking 16521da177e4SLinus Torvalds * the protocol. 16531da177e4SLinus Torvalds */ 16541da177e4SLinus Torvalds 16553e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, 165695c96174SEric Dumazet unsigned int, flags, struct sockaddr __user *, addr, 16573e0fa65fSHeiko Carstens int, addr_len) 16581da177e4SLinus Torvalds { 16591da177e4SLinus Torvalds struct socket *sock; 1660230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16611da177e4SLinus Torvalds int err; 16621da177e4SLinus Torvalds struct msghdr msg; 16631da177e4SLinus Torvalds struct iovec iov; 16646cb153caSBenjamin LaHaise int fput_needed; 16651da177e4SLinus Torvalds 1666602bd0e9SAl Viro err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter); 1667602bd0e9SAl Viro if (unlikely(err)) 1668602bd0e9SAl Viro return err; 1669de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 1670de0fa95cSPavel Emelyanov if (!sock) 16714387ff75SDavid S. Miller goto out; 16726cb153caSBenjamin LaHaise 16731da177e4SLinus Torvalds msg.msg_name = NULL; 16741da177e4SLinus Torvalds msg.msg_control = NULL; 16751da177e4SLinus Torvalds msg.msg_controllen = 0; 16761da177e4SLinus Torvalds msg.msg_namelen = 0; 16776cb153caSBenjamin LaHaise if (addr) { 167843db362dSMaciej Żenczykowski err = move_addr_to_kernel(addr, addr_len, &address); 16791da177e4SLinus Torvalds if (err < 0) 16801da177e4SLinus Torvalds goto out_put; 1681230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 16821da177e4SLinus Torvalds msg.msg_namelen = addr_len; 16831da177e4SLinus Torvalds } 16841da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 16851da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 16861da177e4SLinus Torvalds msg.msg_flags = flags; 1687d8725c86SAl Viro err = sock_sendmsg(sock, &msg); 16881da177e4SLinus Torvalds 16891da177e4SLinus Torvalds out_put: 1690de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 16914387ff75SDavid S. Miller out: 16921da177e4SLinus Torvalds return err; 16931da177e4SLinus Torvalds } 16941da177e4SLinus Torvalds 16951da177e4SLinus Torvalds /* 16961da177e4SLinus Torvalds * Send a datagram down a socket. 16971da177e4SLinus Torvalds */ 16981da177e4SLinus Torvalds 16993e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, 170095c96174SEric Dumazet unsigned int, flags) 17011da177e4SLinus Torvalds { 17021da177e4SLinus Torvalds return sys_sendto(fd, buff, len, flags, NULL, 0); 17031da177e4SLinus Torvalds } 17041da177e4SLinus Torvalds 17051da177e4SLinus Torvalds /* 17061da177e4SLinus Torvalds * Receive a frame from the socket and optionally record the address of the 17071da177e4SLinus Torvalds * sender. We verify the buffers are writable and if needed move the 17081da177e4SLinus Torvalds * sender address from kernel to user space. 17091da177e4SLinus Torvalds */ 17101da177e4SLinus Torvalds 17113e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, 171295c96174SEric Dumazet unsigned int, flags, struct sockaddr __user *, addr, 17133e0fa65fSHeiko Carstens int __user *, addr_len) 17141da177e4SLinus Torvalds { 17151da177e4SLinus Torvalds struct socket *sock; 17161da177e4SLinus Torvalds struct iovec iov; 17171da177e4SLinus Torvalds struct msghdr msg; 1718230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17191da177e4SLinus Torvalds int err, err2; 17206cb153caSBenjamin LaHaise int fput_needed; 17211da177e4SLinus Torvalds 1722602bd0e9SAl Viro err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter); 1723602bd0e9SAl Viro if (unlikely(err)) 1724602bd0e9SAl Viro return err; 1725de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 17261da177e4SLinus Torvalds if (!sock) 1727de0fa95cSPavel Emelyanov goto out; 17281da177e4SLinus Torvalds 17291da177e4SLinus Torvalds msg.msg_control = NULL; 17301da177e4SLinus Torvalds msg.msg_controllen = 0; 1731f3d33426SHannes Frederic Sowa /* Save some cycles and don't copy the address if not needed */ 1732f3d33426SHannes Frederic Sowa msg.msg_name = addr ? (struct sockaddr *)&address : NULL; 1733f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 1734f3d33426SHannes Frederic Sowa msg.msg_namelen = 0; 1735130ed5d1Stadeusz.struk@intel.com msg.msg_iocb = NULL; 17361da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 17371da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 17382da62906SAl Viro err = sock_recvmsg(sock, &msg, flags); 17391da177e4SLinus Torvalds 174089bddce5SStephen Hemminger if (err >= 0 && addr != NULL) { 174143db362dSMaciej Żenczykowski err2 = move_addr_to_user(&address, 1742230b1839SYOSHIFUJI Hideaki msg.msg_namelen, addr, addr_len); 17431da177e4SLinus Torvalds if (err2 < 0) 17441da177e4SLinus Torvalds err = err2; 17451da177e4SLinus Torvalds } 1746de0fa95cSPavel Emelyanov 1747de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 17484387ff75SDavid S. Miller out: 17491da177e4SLinus Torvalds return err; 17501da177e4SLinus Torvalds } 17511da177e4SLinus Torvalds 17521da177e4SLinus Torvalds /* 17531da177e4SLinus Torvalds * Receive a datagram from a socket. 17541da177e4SLinus Torvalds */ 17551da177e4SLinus Torvalds 1756b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size, 1757b7c0ddf5SJan Glauber unsigned int, flags) 17581da177e4SLinus Torvalds { 17591da177e4SLinus Torvalds return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); 17601da177e4SLinus Torvalds } 17611da177e4SLinus Torvalds 17621da177e4SLinus Torvalds /* 17631da177e4SLinus Torvalds * Set a socket option. Because we don't know the option lengths we have 17641da177e4SLinus Torvalds * to pass the user mode parameter for the protocols to sort out. 17651da177e4SLinus Torvalds */ 17661da177e4SLinus Torvalds 176720f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, 176820f37034SHeiko Carstens char __user *, optval, int, optlen) 17691da177e4SLinus Torvalds { 17706cb153caSBenjamin LaHaise int err, fput_needed; 17711da177e4SLinus Torvalds struct socket *sock; 17721da177e4SLinus Torvalds 17731da177e4SLinus Torvalds if (optlen < 0) 17741da177e4SLinus Torvalds return -EINVAL; 17751da177e4SLinus Torvalds 177689bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 177789bddce5SStephen Hemminger if (sock != NULL) { 17781da177e4SLinus Torvalds err = security_socket_setsockopt(sock, level, optname); 17796cb153caSBenjamin LaHaise if (err) 17806cb153caSBenjamin LaHaise goto out_put; 17811da177e4SLinus Torvalds 17821da177e4SLinus Torvalds if (level == SOL_SOCKET) 178389bddce5SStephen Hemminger err = 178489bddce5SStephen Hemminger sock_setsockopt(sock, level, optname, optval, 178589bddce5SStephen Hemminger optlen); 17861da177e4SLinus Torvalds else 178789bddce5SStephen Hemminger err = 178889bddce5SStephen Hemminger sock->ops->setsockopt(sock, level, optname, optval, 178989bddce5SStephen Hemminger optlen); 17906cb153caSBenjamin LaHaise out_put: 17916cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 17921da177e4SLinus Torvalds } 17931da177e4SLinus Torvalds return err; 17941da177e4SLinus Torvalds } 17951da177e4SLinus Torvalds 17961da177e4SLinus Torvalds /* 17971da177e4SLinus Torvalds * Get a socket option. Because we don't know the option lengths we have 17981da177e4SLinus Torvalds * to pass a user mode parameter for the protocols to sort out. 17991da177e4SLinus Torvalds */ 18001da177e4SLinus Torvalds 180120f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, 180220f37034SHeiko Carstens char __user *, optval, int __user *, optlen) 18031da177e4SLinus Torvalds { 18046cb153caSBenjamin LaHaise int err, fput_needed; 18051da177e4SLinus Torvalds struct socket *sock; 18061da177e4SLinus Torvalds 180789bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 180889bddce5SStephen Hemminger if (sock != NULL) { 18096cb153caSBenjamin LaHaise err = security_socket_getsockopt(sock, level, optname); 18106cb153caSBenjamin LaHaise if (err) 18116cb153caSBenjamin LaHaise goto out_put; 18121da177e4SLinus Torvalds 18131da177e4SLinus Torvalds if (level == SOL_SOCKET) 181489bddce5SStephen Hemminger err = 181589bddce5SStephen Hemminger sock_getsockopt(sock, level, optname, optval, 181689bddce5SStephen Hemminger optlen); 18171da177e4SLinus Torvalds else 181889bddce5SStephen Hemminger err = 181989bddce5SStephen Hemminger sock->ops->getsockopt(sock, level, optname, optval, 182089bddce5SStephen Hemminger optlen); 18216cb153caSBenjamin LaHaise out_put: 18226cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18231da177e4SLinus Torvalds } 18241da177e4SLinus Torvalds return err; 18251da177e4SLinus Torvalds } 18261da177e4SLinus Torvalds 18271da177e4SLinus Torvalds /* 18281da177e4SLinus Torvalds * Shutdown a socket. 18291da177e4SLinus Torvalds */ 18301da177e4SLinus Torvalds 1831754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how) 18321da177e4SLinus Torvalds { 18336cb153caSBenjamin LaHaise int err, fput_needed; 18341da177e4SLinus Torvalds struct socket *sock; 18351da177e4SLinus Torvalds 183689bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 183789bddce5SStephen Hemminger if (sock != NULL) { 18381da177e4SLinus Torvalds err = security_socket_shutdown(sock, how); 18396cb153caSBenjamin LaHaise if (!err) 18401da177e4SLinus Torvalds err = sock->ops->shutdown(sock, how); 18416cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18421da177e4SLinus Torvalds } 18431da177e4SLinus Torvalds return err; 18441da177e4SLinus Torvalds } 18451da177e4SLinus Torvalds 18461da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit 18471da177e4SLinus Torvalds * fields which are the same type (int / unsigned) on our platforms. 18481da177e4SLinus Torvalds */ 18491da177e4SLinus Torvalds #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) 18501da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) 18511da177e4SLinus Torvalds #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) 18521da177e4SLinus Torvalds 1853c71d8ebeSTetsuo Handa struct used_address { 1854c71d8ebeSTetsuo Handa struct sockaddr_storage name; 1855c71d8ebeSTetsuo Handa unsigned int name_len; 1856c71d8ebeSTetsuo Handa }; 1857c71d8ebeSTetsuo Handa 1858da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg, 185908adb7daSAl Viro struct user_msghdr __user *umsg, 186008adb7daSAl Viro struct sockaddr __user **save_addr, 186108adb7daSAl Viro struct iovec **iov) 18621661bf36SDan Carpenter { 186308adb7daSAl Viro struct sockaddr __user *uaddr; 186408adb7daSAl Viro struct iovec __user *uiov; 1865c0371da6SAl Viro size_t nr_segs; 186608adb7daSAl Viro ssize_t err; 186708adb7daSAl Viro 186808adb7daSAl Viro if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || 186908adb7daSAl Viro __get_user(uaddr, &umsg->msg_name) || 187008adb7daSAl Viro __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || 187108adb7daSAl Viro __get_user(uiov, &umsg->msg_iov) || 1872c0371da6SAl Viro __get_user(nr_segs, &umsg->msg_iovlen) || 187308adb7daSAl Viro __get_user(kmsg->msg_control, &umsg->msg_control) || 187408adb7daSAl Viro __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || 187508adb7daSAl Viro __get_user(kmsg->msg_flags, &umsg->msg_flags)) 18761661bf36SDan Carpenter return -EFAULT; 1877dbb490b9SMatthew Leach 187808adb7daSAl Viro if (!uaddr) 18796a2a2b3aSAni Sinha kmsg->msg_namelen = 0; 18806a2a2b3aSAni Sinha 1881dbb490b9SMatthew Leach if (kmsg->msg_namelen < 0) 1882dbb490b9SMatthew Leach return -EINVAL; 1883dbb490b9SMatthew Leach 18841661bf36SDan Carpenter if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 1885db31c55aSDan Carpenter kmsg->msg_namelen = sizeof(struct sockaddr_storage); 188608adb7daSAl Viro 188708adb7daSAl Viro if (save_addr) 188808adb7daSAl Viro *save_addr = uaddr; 188908adb7daSAl Viro 189008adb7daSAl Viro if (uaddr && kmsg->msg_namelen) { 189108adb7daSAl Viro if (!save_addr) { 189208adb7daSAl Viro err = move_addr_to_kernel(uaddr, kmsg->msg_namelen, 189308adb7daSAl Viro kmsg->msg_name); 189408adb7daSAl Viro if (err < 0) 189508adb7daSAl Viro return err; 189608adb7daSAl Viro } 189708adb7daSAl Viro } else { 189808adb7daSAl Viro kmsg->msg_name = NULL; 189908adb7daSAl Viro kmsg->msg_namelen = 0; 190008adb7daSAl Viro } 190108adb7daSAl Viro 1902c0371da6SAl Viro if (nr_segs > UIO_MAXIOV) 190308adb7daSAl Viro return -EMSGSIZE; 190408adb7daSAl Viro 19050345f931Stadeusz.struk@intel.com kmsg->msg_iocb = NULL; 19060345f931Stadeusz.struk@intel.com 1907da184284SAl Viro return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs, 1908da184284SAl Viro UIO_FASTIOV, iov, &kmsg->msg_iter); 19091661bf36SDan Carpenter } 19101661bf36SDan Carpenter 1911666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, 191295c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, 191328a94d8fSTom Herbert struct used_address *used_address, 191428a94d8fSTom Herbert unsigned int allowed_msghdr_flags) 19151da177e4SLinus Torvalds { 191689bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 191789bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 1918230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 19191da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 1920b9d717a7SAlex Williamson unsigned char ctl[sizeof(struct cmsghdr) + 20] 1921b9d717a7SAlex Williamson __attribute__ ((aligned(sizeof(__kernel_size_t)))); 1922b9d717a7SAlex Williamson /* 20 is size of ipv6_pktinfo */ 19231da177e4SLinus Torvalds unsigned char *ctl_buf = ctl; 1924d8725c86SAl Viro int ctl_len; 192508adb7daSAl Viro ssize_t err; 19261da177e4SLinus Torvalds 192708adb7daSAl Viro msg_sys->msg_name = &address; 19281da177e4SLinus Torvalds 192908449320SAl Viro if (MSG_CMSG_COMPAT & flags) 193008adb7daSAl Viro err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov); 193108449320SAl Viro else 193208adb7daSAl Viro err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov); 19331da177e4SLinus Torvalds if (err < 0) 1934da184284SAl Viro return err; 19351da177e4SLinus Torvalds 19361da177e4SLinus Torvalds err = -ENOBUFS; 19371da177e4SLinus Torvalds 1938228e548eSAnton Blanchard if (msg_sys->msg_controllen > INT_MAX) 19391da177e4SLinus Torvalds goto out_freeiov; 194028a94d8fSTom Herbert flags |= (msg_sys->msg_flags & allowed_msghdr_flags); 1941228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 19421da177e4SLinus Torvalds if ((MSG_CMSG_COMPAT & flags) && ctl_len) { 194389bddce5SStephen Hemminger err = 1944228e548eSAnton Blanchard cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, 194589bddce5SStephen Hemminger sizeof(ctl)); 19461da177e4SLinus Torvalds if (err) 19471da177e4SLinus Torvalds goto out_freeiov; 1948228e548eSAnton Blanchard ctl_buf = msg_sys->msg_control; 1949228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 19501da177e4SLinus Torvalds } else if (ctl_len) { 195189bddce5SStephen Hemminger if (ctl_len > sizeof(ctl)) { 19521da177e4SLinus Torvalds ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); 19531da177e4SLinus Torvalds if (ctl_buf == NULL) 19541da177e4SLinus Torvalds goto out_freeiov; 19551da177e4SLinus Torvalds } 19561da177e4SLinus Torvalds err = -EFAULT; 19571da177e4SLinus Torvalds /* 1958228e548eSAnton Blanchard * Careful! Before this, msg_sys->msg_control contains a user pointer. 19591da177e4SLinus Torvalds * Afterwards, it will be a kernel pointer. Thus the compiler-assisted 19601da177e4SLinus Torvalds * checking falls down on this. 19611da177e4SLinus Torvalds */ 1962fb8621bbSNamhyung Kim if (copy_from_user(ctl_buf, 1963228e548eSAnton Blanchard (void __user __force *)msg_sys->msg_control, 196489bddce5SStephen Hemminger ctl_len)) 19651da177e4SLinus Torvalds goto out_freectl; 1966228e548eSAnton Blanchard msg_sys->msg_control = ctl_buf; 19671da177e4SLinus Torvalds } 1968228e548eSAnton Blanchard msg_sys->msg_flags = flags; 19691da177e4SLinus Torvalds 19701da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 1971228e548eSAnton Blanchard msg_sys->msg_flags |= MSG_DONTWAIT; 1972c71d8ebeSTetsuo Handa /* 1973c71d8ebeSTetsuo Handa * If this is sendmmsg() and current destination address is same as 1974c71d8ebeSTetsuo Handa * previously succeeded address, omit asking LSM's decision. 1975c71d8ebeSTetsuo Handa * used_address->name_len is initialized to UINT_MAX so that the first 1976c71d8ebeSTetsuo Handa * destination address never matches. 1977c71d8ebeSTetsuo Handa */ 1978bc909d9dSMathieu Desnoyers if (used_address && msg_sys->msg_name && 1979bc909d9dSMathieu Desnoyers used_address->name_len == msg_sys->msg_namelen && 1980bc909d9dSMathieu Desnoyers !memcmp(&used_address->name, msg_sys->msg_name, 1981c71d8ebeSTetsuo Handa used_address->name_len)) { 1982d8725c86SAl Viro err = sock_sendmsg_nosec(sock, msg_sys); 1983c71d8ebeSTetsuo Handa goto out_freectl; 1984c71d8ebeSTetsuo Handa } 1985d8725c86SAl Viro err = sock_sendmsg(sock, msg_sys); 1986c71d8ebeSTetsuo Handa /* 1987c71d8ebeSTetsuo Handa * If this is sendmmsg() and sending to current destination address was 1988c71d8ebeSTetsuo Handa * successful, remember it. 1989c71d8ebeSTetsuo Handa */ 1990c71d8ebeSTetsuo Handa if (used_address && err >= 0) { 1991c71d8ebeSTetsuo Handa used_address->name_len = msg_sys->msg_namelen; 1992bc909d9dSMathieu Desnoyers if (msg_sys->msg_name) 1993bc909d9dSMathieu Desnoyers memcpy(&used_address->name, msg_sys->msg_name, 1994c71d8ebeSTetsuo Handa used_address->name_len); 1995c71d8ebeSTetsuo Handa } 19961da177e4SLinus Torvalds 19971da177e4SLinus Torvalds out_freectl: 19981da177e4SLinus Torvalds if (ctl_buf != ctl) 19991da177e4SLinus Torvalds sock_kfree_s(sock->sk, ctl_buf, ctl_len); 20001da177e4SLinus Torvalds out_freeiov: 2001a74e9106SEric Dumazet kfree(iov); 2002228e548eSAnton Blanchard return err; 2003228e548eSAnton Blanchard } 2004228e548eSAnton Blanchard 2005228e548eSAnton Blanchard /* 2006228e548eSAnton Blanchard * BSD sendmsg interface 2007228e548eSAnton Blanchard */ 2008228e548eSAnton Blanchard 2009666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags) 2010228e548eSAnton Blanchard { 2011228e548eSAnton Blanchard int fput_needed, err; 2012228e548eSAnton Blanchard struct msghdr msg_sys; 20131be374a0SAndy Lutomirski struct socket *sock; 2014228e548eSAnton Blanchard 20151be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2016228e548eSAnton Blanchard if (!sock) 2017228e548eSAnton Blanchard goto out; 2018228e548eSAnton Blanchard 201928a94d8fSTom Herbert err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0); 2020228e548eSAnton Blanchard 20216cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 20221da177e4SLinus Torvalds out: 20231da177e4SLinus Torvalds return err; 20241da177e4SLinus Torvalds } 20251da177e4SLinus Torvalds 2026666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags) 2027a7526eb5SAndy Lutomirski { 2028a7526eb5SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 2029a7526eb5SAndy Lutomirski return -EINVAL; 2030a7526eb5SAndy Lutomirski return __sys_sendmsg(fd, msg, flags); 2031a7526eb5SAndy Lutomirski } 2032a7526eb5SAndy Lutomirski 2033228e548eSAnton Blanchard /* 2034228e548eSAnton Blanchard * Linux sendmmsg interface 2035228e548eSAnton Blanchard */ 2036228e548eSAnton Blanchard 2037228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2038228e548eSAnton Blanchard unsigned int flags) 2039228e548eSAnton Blanchard { 2040228e548eSAnton Blanchard int fput_needed, err, datagrams; 2041228e548eSAnton Blanchard struct socket *sock; 2042228e548eSAnton Blanchard struct mmsghdr __user *entry; 2043228e548eSAnton Blanchard struct compat_mmsghdr __user *compat_entry; 2044228e548eSAnton Blanchard struct msghdr msg_sys; 2045c71d8ebeSTetsuo Handa struct used_address used_address; 2046f092276dSTom Herbert unsigned int oflags = flags; 2047228e548eSAnton Blanchard 204898382f41SAnton Blanchard if (vlen > UIO_MAXIOV) 204998382f41SAnton Blanchard vlen = UIO_MAXIOV; 2050228e548eSAnton Blanchard 2051228e548eSAnton Blanchard datagrams = 0; 2052228e548eSAnton Blanchard 2053228e548eSAnton Blanchard sock = sockfd_lookup_light(fd, &err, &fput_needed); 2054228e548eSAnton Blanchard if (!sock) 2055228e548eSAnton Blanchard return err; 2056228e548eSAnton Blanchard 2057c71d8ebeSTetsuo Handa used_address.name_len = UINT_MAX; 2058228e548eSAnton Blanchard entry = mmsg; 2059228e548eSAnton Blanchard compat_entry = (struct compat_mmsghdr __user *)mmsg; 2060728ffb86SAnton Blanchard err = 0; 2061f092276dSTom Herbert flags |= MSG_BATCH; 2062228e548eSAnton Blanchard 2063228e548eSAnton Blanchard while (datagrams < vlen) { 2064f092276dSTom Herbert if (datagrams == vlen - 1) 2065f092276dSTom Herbert flags = oflags; 2066f092276dSTom Herbert 2067228e548eSAnton Blanchard if (MSG_CMSG_COMPAT & flags) { 2068666547ffSAl Viro err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry, 206928a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2070228e548eSAnton Blanchard if (err < 0) 2071228e548eSAnton Blanchard break; 2072228e548eSAnton Blanchard err = __put_user(err, &compat_entry->msg_len); 2073228e548eSAnton Blanchard ++compat_entry; 2074228e548eSAnton Blanchard } else { 2075a7526eb5SAndy Lutomirski err = ___sys_sendmsg(sock, 2076666547ffSAl Viro (struct user_msghdr __user *)entry, 207728a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2078228e548eSAnton Blanchard if (err < 0) 2079228e548eSAnton Blanchard break; 2080228e548eSAnton Blanchard err = put_user(err, &entry->msg_len); 2081228e548eSAnton Blanchard ++entry; 2082228e548eSAnton Blanchard } 2083228e548eSAnton Blanchard 2084228e548eSAnton Blanchard if (err) 2085228e548eSAnton Blanchard break; 2086228e548eSAnton Blanchard ++datagrams; 20873023898bSSoheil Hassas Yeganeh if (msg_data_left(&msg_sys)) 20883023898bSSoheil Hassas Yeganeh break; 2089a78cb84cSEric Dumazet cond_resched(); 2090228e548eSAnton Blanchard } 2091228e548eSAnton Blanchard 2092228e548eSAnton Blanchard fput_light(sock->file, fput_needed); 2093228e548eSAnton Blanchard 2094728ffb86SAnton Blanchard /* We only return an error if no datagrams were able to be sent */ 2095728ffb86SAnton Blanchard if (datagrams != 0) 2096228e548eSAnton Blanchard return datagrams; 2097228e548eSAnton Blanchard 2098228e548eSAnton Blanchard return err; 2099228e548eSAnton Blanchard } 2100228e548eSAnton Blanchard 2101228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, 2102228e548eSAnton Blanchard unsigned int, vlen, unsigned int, flags) 2103228e548eSAnton Blanchard { 21041be374a0SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 21051be374a0SAndy Lutomirski return -EINVAL; 2106228e548eSAnton Blanchard return __sys_sendmmsg(fd, mmsg, vlen, flags); 2107228e548eSAnton Blanchard } 2108228e548eSAnton Blanchard 2109666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, 211095c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, int nosec) 21111da177e4SLinus Torvalds { 211289bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 211389bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 21141da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV]; 21151da177e4SLinus Torvalds struct iovec *iov = iovstack; 21161da177e4SLinus Torvalds unsigned long cmsg_ptr; 21172da62906SAl Viro int len; 211808adb7daSAl Viro ssize_t err; 21191da177e4SLinus Torvalds 21201da177e4SLinus Torvalds /* kernel mode address */ 2121230b1839SYOSHIFUJI Hideaki struct sockaddr_storage addr; 21221da177e4SLinus Torvalds 21231da177e4SLinus Torvalds /* user mode address pointers */ 21241da177e4SLinus Torvalds struct sockaddr __user *uaddr; 212508adb7daSAl Viro int __user *uaddr_len = COMPAT_NAMELEN(msg); 21261da177e4SLinus Torvalds 212708adb7daSAl Viro msg_sys->msg_name = &addr; 21281da177e4SLinus Torvalds 2129f3d33426SHannes Frederic Sowa if (MSG_CMSG_COMPAT & flags) 213008adb7daSAl Viro err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov); 2131f3d33426SHannes Frederic Sowa else 213208adb7daSAl Viro err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov); 21331da177e4SLinus Torvalds if (err < 0) 2134da184284SAl Viro return err; 21351da177e4SLinus Torvalds 2136a2e27255SArnaldo Carvalho de Melo cmsg_ptr = (unsigned long)msg_sys->msg_control; 2137a2e27255SArnaldo Carvalho de Melo msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 21381da177e4SLinus Torvalds 2139f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 2140f3d33426SHannes Frederic Sowa msg_sys->msg_namelen = 0; 2141f3d33426SHannes Frederic Sowa 21421da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 21431da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 21442da62906SAl Viro err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags); 21451da177e4SLinus Torvalds if (err < 0) 21461da177e4SLinus Torvalds goto out_freeiov; 21471da177e4SLinus Torvalds len = err; 21481da177e4SLinus Torvalds 21491da177e4SLinus Torvalds if (uaddr != NULL) { 215043db362dSMaciej Żenczykowski err = move_addr_to_user(&addr, 2151a2e27255SArnaldo Carvalho de Melo msg_sys->msg_namelen, uaddr, 215289bddce5SStephen Hemminger uaddr_len); 21531da177e4SLinus Torvalds if (err < 0) 21541da177e4SLinus Torvalds goto out_freeiov; 21551da177e4SLinus Torvalds } 2156a2e27255SArnaldo Carvalho de Melo err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT), 215737f7f421SDavid S. Miller COMPAT_FLAGS(msg)); 21581da177e4SLinus Torvalds if (err) 21591da177e4SLinus Torvalds goto out_freeiov; 21601da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) 2161a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 21621da177e4SLinus Torvalds &msg_compat->msg_controllen); 21631da177e4SLinus Torvalds else 2164a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 21651da177e4SLinus Torvalds &msg->msg_controllen); 21661da177e4SLinus Torvalds if (err) 21671da177e4SLinus Torvalds goto out_freeiov; 21681da177e4SLinus Torvalds err = len; 21691da177e4SLinus Torvalds 21701da177e4SLinus Torvalds out_freeiov: 2171a74e9106SEric Dumazet kfree(iov); 2172a2e27255SArnaldo Carvalho de Melo return err; 2173a2e27255SArnaldo Carvalho de Melo } 2174a2e27255SArnaldo Carvalho de Melo 2175a2e27255SArnaldo Carvalho de Melo /* 2176a2e27255SArnaldo Carvalho de Melo * BSD recvmsg interface 2177a2e27255SArnaldo Carvalho de Melo */ 2178a2e27255SArnaldo Carvalho de Melo 2179666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags) 2180a2e27255SArnaldo Carvalho de Melo { 2181a2e27255SArnaldo Carvalho de Melo int fput_needed, err; 2182a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 21831be374a0SAndy Lutomirski struct socket *sock; 2184a2e27255SArnaldo Carvalho de Melo 21851be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2186a2e27255SArnaldo Carvalho de Melo if (!sock) 2187a2e27255SArnaldo Carvalho de Melo goto out; 2188a2e27255SArnaldo Carvalho de Melo 2189a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2190a2e27255SArnaldo Carvalho de Melo 21916cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 21921da177e4SLinus Torvalds out: 21931da177e4SLinus Torvalds return err; 21941da177e4SLinus Torvalds } 21951da177e4SLinus Torvalds 2196666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg, 2197a7526eb5SAndy Lutomirski unsigned int, flags) 2198a7526eb5SAndy Lutomirski { 2199a7526eb5SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 2200a7526eb5SAndy Lutomirski return -EINVAL; 2201a7526eb5SAndy Lutomirski return __sys_recvmsg(fd, msg, flags); 2202a7526eb5SAndy Lutomirski } 2203a7526eb5SAndy Lutomirski 2204a2e27255SArnaldo Carvalho de Melo /* 2205a2e27255SArnaldo Carvalho de Melo * Linux recvmmsg interface 2206a2e27255SArnaldo Carvalho de Melo */ 22071da177e4SLinus Torvalds 2208a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2209a2e27255SArnaldo Carvalho de Melo unsigned int flags, struct timespec *timeout) 2210a2e27255SArnaldo Carvalho de Melo { 2211a2e27255SArnaldo Carvalho de Melo int fput_needed, err, datagrams; 2212a2e27255SArnaldo Carvalho de Melo struct socket *sock; 2213a2e27255SArnaldo Carvalho de Melo struct mmsghdr __user *entry; 2214d7256d0eSJean-Mickael Guerin struct compat_mmsghdr __user *compat_entry; 2215a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2216766b9f92SDeepa Dinamani struct timespec64 end_time; 2217766b9f92SDeepa Dinamani struct timespec64 timeout64; 2218a2e27255SArnaldo Carvalho de Melo 2219a2e27255SArnaldo Carvalho de Melo if (timeout && 2220a2e27255SArnaldo Carvalho de Melo poll_select_set_timeout(&end_time, timeout->tv_sec, 2221a2e27255SArnaldo Carvalho de Melo timeout->tv_nsec)) 2222a2e27255SArnaldo Carvalho de Melo return -EINVAL; 2223a2e27255SArnaldo Carvalho de Melo 2224a2e27255SArnaldo Carvalho de Melo datagrams = 0; 2225a2e27255SArnaldo Carvalho de Melo 2226a2e27255SArnaldo Carvalho de Melo sock = sockfd_lookup_light(fd, &err, &fput_needed); 2227a2e27255SArnaldo Carvalho de Melo if (!sock) 2228a2e27255SArnaldo Carvalho de Melo return err; 2229a2e27255SArnaldo Carvalho de Melo 2230a2e27255SArnaldo Carvalho de Melo err = sock_error(sock->sk); 2231a2e27255SArnaldo Carvalho de Melo if (err) 2232a2e27255SArnaldo Carvalho de Melo goto out_put; 2233a2e27255SArnaldo Carvalho de Melo 2234a2e27255SArnaldo Carvalho de Melo entry = mmsg; 2235d7256d0eSJean-Mickael Guerin compat_entry = (struct compat_mmsghdr __user *)mmsg; 2236a2e27255SArnaldo Carvalho de Melo 2237a2e27255SArnaldo Carvalho de Melo while (datagrams < vlen) { 2238a2e27255SArnaldo Carvalho de Melo /* 2239a2e27255SArnaldo Carvalho de Melo * No need to ask LSM for more than the first datagram. 2240a2e27255SArnaldo Carvalho de Melo */ 2241d7256d0eSJean-Mickael Guerin if (MSG_CMSG_COMPAT & flags) { 2242666547ffSAl Viro err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry, 2243b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2244b9eb8b87SAnton Blanchard datagrams); 2245d7256d0eSJean-Mickael Guerin if (err < 0) 2246d7256d0eSJean-Mickael Guerin break; 2247d7256d0eSJean-Mickael Guerin err = __put_user(err, &compat_entry->msg_len); 2248d7256d0eSJean-Mickael Guerin ++compat_entry; 2249d7256d0eSJean-Mickael Guerin } else { 2250a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, 2251666547ffSAl Viro (struct user_msghdr __user *)entry, 2252b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2253b9eb8b87SAnton Blanchard datagrams); 2254a2e27255SArnaldo Carvalho de Melo if (err < 0) 2255a2e27255SArnaldo Carvalho de Melo break; 2256a2e27255SArnaldo Carvalho de Melo err = put_user(err, &entry->msg_len); 2257d7256d0eSJean-Mickael Guerin ++entry; 2258d7256d0eSJean-Mickael Guerin } 2259d7256d0eSJean-Mickael Guerin 2260a2e27255SArnaldo Carvalho de Melo if (err) 2261a2e27255SArnaldo Carvalho de Melo break; 2262a2e27255SArnaldo Carvalho de Melo ++datagrams; 2263a2e27255SArnaldo Carvalho de Melo 226471c5c159SBrandon L Black /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ 226571c5c159SBrandon L Black if (flags & MSG_WAITFORONE) 226671c5c159SBrandon L Black flags |= MSG_DONTWAIT; 226771c5c159SBrandon L Black 2268a2e27255SArnaldo Carvalho de Melo if (timeout) { 2269766b9f92SDeepa Dinamani ktime_get_ts64(&timeout64); 2270766b9f92SDeepa Dinamani *timeout = timespec64_to_timespec( 2271766b9f92SDeepa Dinamani timespec64_sub(end_time, timeout64)); 2272a2e27255SArnaldo Carvalho de Melo if (timeout->tv_sec < 0) { 2273a2e27255SArnaldo Carvalho de Melo timeout->tv_sec = timeout->tv_nsec = 0; 2274a2e27255SArnaldo Carvalho de Melo break; 2275a2e27255SArnaldo Carvalho de Melo } 2276a2e27255SArnaldo Carvalho de Melo 2277a2e27255SArnaldo Carvalho de Melo /* Timeout, return less than vlen datagrams */ 2278a2e27255SArnaldo Carvalho de Melo if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) 2279a2e27255SArnaldo Carvalho de Melo break; 2280a2e27255SArnaldo Carvalho de Melo } 2281a2e27255SArnaldo Carvalho de Melo 2282a2e27255SArnaldo Carvalho de Melo /* Out of band data, return right away */ 2283a2e27255SArnaldo Carvalho de Melo if (msg_sys.msg_flags & MSG_OOB) 2284a2e27255SArnaldo Carvalho de Melo break; 2285a78cb84cSEric Dumazet cond_resched(); 2286a2e27255SArnaldo Carvalho de Melo } 2287a2e27255SArnaldo Carvalho de Melo 2288a2e27255SArnaldo Carvalho de Melo if (err == 0) 228934b88a68SArnaldo Carvalho de Melo goto out_put; 2290a2e27255SArnaldo Carvalho de Melo 229134b88a68SArnaldo Carvalho de Melo if (datagrams == 0) { 229234b88a68SArnaldo Carvalho de Melo datagrams = err; 229334b88a68SArnaldo Carvalho de Melo goto out_put; 229434b88a68SArnaldo Carvalho de Melo } 229534b88a68SArnaldo Carvalho de Melo 2296a2e27255SArnaldo Carvalho de Melo /* 2297a2e27255SArnaldo Carvalho de Melo * We may return less entries than requested (vlen) if the 2298a2e27255SArnaldo Carvalho de Melo * sock is non block and there aren't enough datagrams... 2299a2e27255SArnaldo Carvalho de Melo */ 2300a2e27255SArnaldo Carvalho de Melo if (err != -EAGAIN) { 2301a2e27255SArnaldo Carvalho de Melo /* 2302a2e27255SArnaldo Carvalho de Melo * ... or if recvmsg returns an error after we 2303a2e27255SArnaldo Carvalho de Melo * received some datagrams, where we record the 2304a2e27255SArnaldo Carvalho de Melo * error to return on the next call or if the 2305a2e27255SArnaldo Carvalho de Melo * app asks about it using getsockopt(SO_ERROR). 2306a2e27255SArnaldo Carvalho de Melo */ 2307a2e27255SArnaldo Carvalho de Melo sock->sk->sk_err = -err; 2308a2e27255SArnaldo Carvalho de Melo } 230934b88a68SArnaldo Carvalho de Melo out_put: 231034b88a68SArnaldo Carvalho de Melo fput_light(sock->file, fput_needed); 2311a2e27255SArnaldo Carvalho de Melo 2312a2e27255SArnaldo Carvalho de Melo return datagrams; 2313a2e27255SArnaldo Carvalho de Melo } 2314a2e27255SArnaldo Carvalho de Melo 2315a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, 2316a2e27255SArnaldo Carvalho de Melo unsigned int, vlen, unsigned int, flags, 2317a2e27255SArnaldo Carvalho de Melo struct timespec __user *, timeout) 2318a2e27255SArnaldo Carvalho de Melo { 2319a2e27255SArnaldo Carvalho de Melo int datagrams; 2320a2e27255SArnaldo Carvalho de Melo struct timespec timeout_sys; 2321a2e27255SArnaldo Carvalho de Melo 23221be374a0SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 23231be374a0SAndy Lutomirski return -EINVAL; 23241be374a0SAndy Lutomirski 2325a2e27255SArnaldo Carvalho de Melo if (!timeout) 2326a2e27255SArnaldo Carvalho de Melo return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); 2327a2e27255SArnaldo Carvalho de Melo 2328a2e27255SArnaldo Carvalho de Melo if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys))) 2329a2e27255SArnaldo Carvalho de Melo return -EFAULT; 2330a2e27255SArnaldo Carvalho de Melo 2331a2e27255SArnaldo Carvalho de Melo datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys); 2332a2e27255SArnaldo Carvalho de Melo 2333a2e27255SArnaldo Carvalho de Melo if (datagrams > 0 && 2334a2e27255SArnaldo Carvalho de Melo copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys))) 2335a2e27255SArnaldo Carvalho de Melo datagrams = -EFAULT; 2336a2e27255SArnaldo Carvalho de Melo 2337a2e27255SArnaldo Carvalho de Melo return datagrams; 2338a2e27255SArnaldo Carvalho de Melo } 2339a2e27255SArnaldo Carvalho de Melo 2340a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL 23411da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */ 23421da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long)) 2343228e548eSAnton Blanchard static const unsigned char nargs[21] = { 234489bddce5SStephen Hemminger AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 23451da177e4SLinus Torvalds AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 2346aaca0bdcSUlrich Drepper AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 2347228e548eSAnton Blanchard AL(4), AL(5), AL(4) 234889bddce5SStephen Hemminger }; 234989bddce5SStephen Hemminger 23501da177e4SLinus Torvalds #undef AL 23511da177e4SLinus Torvalds 23521da177e4SLinus Torvalds /* 23531da177e4SLinus Torvalds * System call vectors. 23541da177e4SLinus Torvalds * 23551da177e4SLinus Torvalds * Argument checking cleaned up. Saved 20% in size. 23561da177e4SLinus Torvalds * This function doesn't need to set the kernel lock because 23571da177e4SLinus Torvalds * it is set by the callees. 23581da177e4SLinus Torvalds */ 23591da177e4SLinus Torvalds 23603e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) 23611da177e4SLinus Torvalds { 23622950fa9dSChen Gang unsigned long a[AUDITSC_ARGS]; 23631da177e4SLinus Torvalds unsigned long a0, a1; 23641da177e4SLinus Torvalds int err; 236547379052SArjan van de Ven unsigned int len; 23661da177e4SLinus Torvalds 2367228e548eSAnton Blanchard if (call < 1 || call > SYS_SENDMMSG) 23681da177e4SLinus Torvalds return -EINVAL; 23691da177e4SLinus Torvalds 237047379052SArjan van de Ven len = nargs[call]; 237147379052SArjan van de Ven if (len > sizeof(a)) 237247379052SArjan van de Ven return -EINVAL; 237347379052SArjan van de Ven 23741da177e4SLinus Torvalds /* copy_from_user should be SMP safe. */ 237547379052SArjan van de Ven if (copy_from_user(a, args, len)) 23761da177e4SLinus Torvalds return -EFAULT; 23771da177e4SLinus Torvalds 23782950fa9dSChen Gang err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); 23792950fa9dSChen Gang if (err) 23802950fa9dSChen Gang return err; 23813ec3b2fbSDavid Woodhouse 23821da177e4SLinus Torvalds a0 = a[0]; 23831da177e4SLinus Torvalds a1 = a[1]; 23841da177e4SLinus Torvalds 238589bddce5SStephen Hemminger switch (call) { 23861da177e4SLinus Torvalds case SYS_SOCKET: 23871da177e4SLinus Torvalds err = sys_socket(a0, a1, a[2]); 23881da177e4SLinus Torvalds break; 23891da177e4SLinus Torvalds case SYS_BIND: 23901da177e4SLinus Torvalds err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]); 23911da177e4SLinus Torvalds break; 23921da177e4SLinus Torvalds case SYS_CONNECT: 23931da177e4SLinus Torvalds err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]); 23941da177e4SLinus Torvalds break; 23951da177e4SLinus Torvalds case SYS_LISTEN: 23961da177e4SLinus Torvalds err = sys_listen(a0, a1); 23971da177e4SLinus Torvalds break; 23981da177e4SLinus Torvalds case SYS_ACCEPT: 2399de11defeSUlrich Drepper err = sys_accept4(a0, (struct sockaddr __user *)a1, 2400aaca0bdcSUlrich Drepper (int __user *)a[2], 0); 24011da177e4SLinus Torvalds break; 24021da177e4SLinus Torvalds case SYS_GETSOCKNAME: 240389bddce5SStephen Hemminger err = 240489bddce5SStephen Hemminger sys_getsockname(a0, (struct sockaddr __user *)a1, 240589bddce5SStephen Hemminger (int __user *)a[2]); 24061da177e4SLinus Torvalds break; 24071da177e4SLinus Torvalds case SYS_GETPEERNAME: 240889bddce5SStephen Hemminger err = 240989bddce5SStephen Hemminger sys_getpeername(a0, (struct sockaddr __user *)a1, 241089bddce5SStephen Hemminger (int __user *)a[2]); 24111da177e4SLinus Torvalds break; 24121da177e4SLinus Torvalds case SYS_SOCKETPAIR: 24131da177e4SLinus Torvalds err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]); 24141da177e4SLinus Torvalds break; 24151da177e4SLinus Torvalds case SYS_SEND: 24161da177e4SLinus Torvalds err = sys_send(a0, (void __user *)a1, a[2], a[3]); 24171da177e4SLinus Torvalds break; 24181da177e4SLinus Torvalds case SYS_SENDTO: 24191da177e4SLinus Torvalds err = sys_sendto(a0, (void __user *)a1, a[2], a[3], 24201da177e4SLinus Torvalds (struct sockaddr __user *)a[4], a[5]); 24211da177e4SLinus Torvalds break; 24221da177e4SLinus Torvalds case SYS_RECV: 24231da177e4SLinus Torvalds err = sys_recv(a0, (void __user *)a1, a[2], a[3]); 24241da177e4SLinus Torvalds break; 24251da177e4SLinus Torvalds case SYS_RECVFROM: 24261da177e4SLinus Torvalds err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 242789bddce5SStephen Hemminger (struct sockaddr __user *)a[4], 242889bddce5SStephen Hemminger (int __user *)a[5]); 24291da177e4SLinus Torvalds break; 24301da177e4SLinus Torvalds case SYS_SHUTDOWN: 24311da177e4SLinus Torvalds err = sys_shutdown(a0, a1); 24321da177e4SLinus Torvalds break; 24331da177e4SLinus Torvalds case SYS_SETSOCKOPT: 24341da177e4SLinus Torvalds err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]); 24351da177e4SLinus Torvalds break; 24361da177e4SLinus Torvalds case SYS_GETSOCKOPT: 243789bddce5SStephen Hemminger err = 243889bddce5SStephen Hemminger sys_getsockopt(a0, a1, a[2], (char __user *)a[3], 243989bddce5SStephen Hemminger (int __user *)a[4]); 24401da177e4SLinus Torvalds break; 24411da177e4SLinus Torvalds case SYS_SENDMSG: 2442666547ffSAl Viro err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]); 24431da177e4SLinus Torvalds break; 2444228e548eSAnton Blanchard case SYS_SENDMMSG: 2445228e548eSAnton Blanchard err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); 2446228e548eSAnton Blanchard break; 24471da177e4SLinus Torvalds case SYS_RECVMSG: 2448666547ffSAl Viro err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]); 24491da177e4SLinus Torvalds break; 2450a2e27255SArnaldo Carvalho de Melo case SYS_RECVMMSG: 2451a2e27255SArnaldo Carvalho de Melo err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], 2452a2e27255SArnaldo Carvalho de Melo (struct timespec __user *)a[4]); 2453a2e27255SArnaldo Carvalho de Melo break; 2454de11defeSUlrich Drepper case SYS_ACCEPT4: 2455de11defeSUlrich Drepper err = sys_accept4(a0, (struct sockaddr __user *)a1, 2456de11defeSUlrich Drepper (int __user *)a[2], a[3]); 2457aaca0bdcSUlrich Drepper break; 24581da177e4SLinus Torvalds default: 24591da177e4SLinus Torvalds err = -EINVAL; 24601da177e4SLinus Torvalds break; 24611da177e4SLinus Torvalds } 24621da177e4SLinus Torvalds return err; 24631da177e4SLinus Torvalds } 24641da177e4SLinus Torvalds 24651da177e4SLinus Torvalds #endif /* __ARCH_WANT_SYS_SOCKETCALL */ 24661da177e4SLinus Torvalds 246755737fdaSStephen Hemminger /** 246855737fdaSStephen Hemminger * sock_register - add a socket protocol handler 246955737fdaSStephen Hemminger * @ops: description of protocol 247055737fdaSStephen Hemminger * 24711da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 24721da177e4SLinus Torvalds * advertise its address family, and have it linked into the 2473e793c0f7SMasanari Iida * socket interface. The value ops->family corresponds to the 247455737fdaSStephen Hemminger * socket system call protocol family. 24751da177e4SLinus Torvalds */ 2476f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops) 24771da177e4SLinus Torvalds { 24781da177e4SLinus Torvalds int err; 24791da177e4SLinus Torvalds 24801da177e4SLinus Torvalds if (ops->family >= NPROTO) { 24813410f22eSYang Yingliang pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO); 24821da177e4SLinus Torvalds return -ENOBUFS; 24831da177e4SLinus Torvalds } 248455737fdaSStephen Hemminger 248555737fdaSStephen Hemminger spin_lock(&net_family_lock); 2486190683a9SEric Dumazet if (rcu_dereference_protected(net_families[ops->family], 2487190683a9SEric Dumazet lockdep_is_held(&net_family_lock))) 24881da177e4SLinus Torvalds err = -EEXIST; 248955737fdaSStephen Hemminger else { 2490cf778b00SEric Dumazet rcu_assign_pointer(net_families[ops->family], ops); 24911da177e4SLinus Torvalds err = 0; 24921da177e4SLinus Torvalds } 249355737fdaSStephen Hemminger spin_unlock(&net_family_lock); 249455737fdaSStephen Hemminger 24953410f22eSYang Yingliang pr_info("NET: Registered protocol family %d\n", ops->family); 24961da177e4SLinus Torvalds return err; 24971da177e4SLinus Torvalds } 2498c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register); 24991da177e4SLinus Torvalds 250055737fdaSStephen Hemminger /** 250155737fdaSStephen Hemminger * sock_unregister - remove a protocol handler 250255737fdaSStephen Hemminger * @family: protocol family to remove 250355737fdaSStephen Hemminger * 25041da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 25051da177e4SLinus Torvalds * remove its address family, and have it unlinked from the 250655737fdaSStephen Hemminger * new socket creation. 250755737fdaSStephen Hemminger * 250855737fdaSStephen Hemminger * If protocol handler is a module, then it can use module reference 250955737fdaSStephen Hemminger * counts to protect against new references. If protocol handler is not 251055737fdaSStephen Hemminger * a module then it needs to provide its own protection in 251155737fdaSStephen Hemminger * the ops->create routine. 25121da177e4SLinus Torvalds */ 2513f0fd27d4SStephen Hemminger void sock_unregister(int family) 25141da177e4SLinus Torvalds { 2515f0fd27d4SStephen Hemminger BUG_ON(family < 0 || family >= NPROTO); 25161da177e4SLinus Torvalds 251755737fdaSStephen Hemminger spin_lock(&net_family_lock); 2518a9b3cd7fSStephen Hemminger RCU_INIT_POINTER(net_families[family], NULL); 251955737fdaSStephen Hemminger spin_unlock(&net_family_lock); 252055737fdaSStephen Hemminger 252155737fdaSStephen Hemminger synchronize_rcu(); 252255737fdaSStephen Hemminger 25233410f22eSYang Yingliang pr_info("NET: Unregistered protocol family %d\n", family); 25241da177e4SLinus Torvalds } 2525c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister); 25261da177e4SLinus Torvalds 252777d76ea3SAndi Kleen static int __init sock_init(void) 25281da177e4SLinus Torvalds { 2529b3e19d92SNick Piggin int err; 25302ca794e5SEric W. Biederman /* 25312ca794e5SEric W. Biederman * Initialize the network sysctl infrastructure. 25322ca794e5SEric W. Biederman */ 25332ca794e5SEric W. Biederman err = net_sysctl_init(); 25342ca794e5SEric W. Biederman if (err) 25352ca794e5SEric W. Biederman goto out; 2536b3e19d92SNick Piggin 25371da177e4SLinus Torvalds /* 25381da177e4SLinus Torvalds * Initialize skbuff SLAB cache 25391da177e4SLinus Torvalds */ 25401da177e4SLinus Torvalds skb_init(); 25411da177e4SLinus Torvalds 25421da177e4SLinus Torvalds /* 25431da177e4SLinus Torvalds * Initialize the protocols module. 25441da177e4SLinus Torvalds */ 25451da177e4SLinus Torvalds 25461da177e4SLinus Torvalds init_inodecache(); 2547b3e19d92SNick Piggin 2548b3e19d92SNick Piggin err = register_filesystem(&sock_fs_type); 2549b3e19d92SNick Piggin if (err) 2550b3e19d92SNick Piggin goto out_fs; 25511da177e4SLinus Torvalds sock_mnt = kern_mount(&sock_fs_type); 2552b3e19d92SNick Piggin if (IS_ERR(sock_mnt)) { 2553b3e19d92SNick Piggin err = PTR_ERR(sock_mnt); 2554b3e19d92SNick Piggin goto out_mount; 2555b3e19d92SNick Piggin } 255677d76ea3SAndi Kleen 255777d76ea3SAndi Kleen /* The real protocol initialization is performed in later initcalls. 25581da177e4SLinus Torvalds */ 25591da177e4SLinus Torvalds 25601da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER 25616d11cfdbSPablo Neira Ayuso err = netfilter_init(); 25626d11cfdbSPablo Neira Ayuso if (err) 25636d11cfdbSPablo Neira Ayuso goto out; 25641da177e4SLinus Torvalds #endif 2565cbeb321aSDavid S. Miller 2566408eccceSDaniel Borkmann ptp_classifier_init(); 2567c1f19b51SRichard Cochran 2568b3e19d92SNick Piggin out: 2569b3e19d92SNick Piggin return err; 2570b3e19d92SNick Piggin 2571b3e19d92SNick Piggin out_mount: 2572b3e19d92SNick Piggin unregister_filesystem(&sock_fs_type); 2573b3e19d92SNick Piggin out_fs: 2574b3e19d92SNick Piggin goto out; 25751da177e4SLinus Torvalds } 25761da177e4SLinus Torvalds 257777d76ea3SAndi Kleen core_initcall(sock_init); /* early initcall */ 257877d76ea3SAndi Kleen 25791da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 25801da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq) 25811da177e4SLinus Torvalds { 25821da177e4SLinus Torvalds int cpu; 25831da177e4SLinus Torvalds int counter = 0; 25841da177e4SLinus Torvalds 25856f912042SKAMEZAWA Hiroyuki for_each_possible_cpu(cpu) 25861da177e4SLinus Torvalds counter += per_cpu(sockets_in_use, cpu); 25871da177e4SLinus Torvalds 25881da177e4SLinus Torvalds /* It can be negative, by the way. 8) */ 25891da177e4SLinus Torvalds if (counter < 0) 25901da177e4SLinus Torvalds counter = 0; 25911da177e4SLinus Torvalds 25921da177e4SLinus Torvalds seq_printf(seq, "sockets: used %d\n", counter); 25931da177e4SLinus Torvalds } 25941da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */ 25951da177e4SLinus Torvalds 259689bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 25976b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock, 2598644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 25997a229387SArnd Bergmann { 26007a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 26017a229387SArnd Bergmann struct timeval ktv; 26027a229387SArnd Bergmann int err; 26037a229387SArnd Bergmann 26047a229387SArnd Bergmann set_fs(KERNEL_DS); 26056b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); 26067a229387SArnd Bergmann set_fs(old_fs); 2607644595f8SH. Peter Anvin if (!err) 2608ed6fe9d6SMikulas Patocka err = compat_put_timeval(&ktv, up); 2609644595f8SH. Peter Anvin 26107a229387SArnd Bergmann return err; 26117a229387SArnd Bergmann } 26127a229387SArnd Bergmann 26136b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock, 2614644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 26157a229387SArnd Bergmann { 26167a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 26177a229387SArnd Bergmann struct timespec kts; 26187a229387SArnd Bergmann int err; 26197a229387SArnd Bergmann 26207a229387SArnd Bergmann set_fs(KERNEL_DS); 26216b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); 26227a229387SArnd Bergmann set_fs(old_fs); 2623644595f8SH. Peter Anvin if (!err) 2624ed6fe9d6SMikulas Patocka err = compat_put_timespec(&kts, up); 2625644595f8SH. Peter Anvin 26267a229387SArnd Bergmann return err; 26277a229387SArnd Bergmann } 26287a229387SArnd Bergmann 26296b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32) 26307a229387SArnd Bergmann { 26317a229387SArnd Bergmann struct ifreq __user *uifr; 26327a229387SArnd Bergmann int err; 26337a229387SArnd Bergmann 26347a229387SArnd Bergmann uifr = compat_alloc_user_space(sizeof(struct ifreq)); 26356b96018bSArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 26367a229387SArnd Bergmann return -EFAULT; 26377a229387SArnd Bergmann 26386b96018bSArnd Bergmann err = dev_ioctl(net, SIOCGIFNAME, uifr); 26397a229387SArnd Bergmann if (err) 26407a229387SArnd Bergmann return err; 26417a229387SArnd Bergmann 26426b96018bSArnd Bergmann if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq))) 26437a229387SArnd Bergmann return -EFAULT; 26447a229387SArnd Bergmann 26457a229387SArnd Bergmann return 0; 26467a229387SArnd Bergmann } 26477a229387SArnd Bergmann 26486b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) 26497a229387SArnd Bergmann { 26506b96018bSArnd Bergmann struct compat_ifconf ifc32; 26517a229387SArnd Bergmann struct ifconf ifc; 26527a229387SArnd Bergmann struct ifconf __user *uifc; 26536b96018bSArnd Bergmann struct compat_ifreq __user *ifr32; 26547a229387SArnd Bergmann struct ifreq __user *ifr; 26557a229387SArnd Bergmann unsigned int i, j; 26567a229387SArnd Bergmann int err; 26577a229387SArnd Bergmann 26586b96018bSArnd Bergmann if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) 26597a229387SArnd Bergmann return -EFAULT; 26607a229387SArnd Bergmann 266143da5f2eSMathias Krause memset(&ifc, 0, sizeof(ifc)); 26627a229387SArnd Bergmann if (ifc32.ifcbuf == 0) { 26637a229387SArnd Bergmann ifc32.ifc_len = 0; 26647a229387SArnd Bergmann ifc.ifc_len = 0; 26657a229387SArnd Bergmann ifc.ifc_req = NULL; 26667a229387SArnd Bergmann uifc = compat_alloc_user_space(sizeof(struct ifconf)); 26677a229387SArnd Bergmann } else { 26686b96018bSArnd Bergmann size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) * 26697a229387SArnd Bergmann sizeof(struct ifreq); 26707a229387SArnd Bergmann uifc = compat_alloc_user_space(sizeof(struct ifconf) + len); 26717a229387SArnd Bergmann ifc.ifc_len = len; 26727a229387SArnd Bergmann ifr = ifc.ifc_req = (void __user *)(uifc + 1); 26737a229387SArnd Bergmann ifr32 = compat_ptr(ifc32.ifcbuf); 26746b96018bSArnd Bergmann for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) { 26756b96018bSArnd Bergmann if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq))) 26767a229387SArnd Bergmann return -EFAULT; 26777a229387SArnd Bergmann ifr++; 26787a229387SArnd Bergmann ifr32++; 26797a229387SArnd Bergmann } 26807a229387SArnd Bergmann } 26817a229387SArnd Bergmann if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) 26827a229387SArnd Bergmann return -EFAULT; 26837a229387SArnd Bergmann 26846b96018bSArnd Bergmann err = dev_ioctl(net, SIOCGIFCONF, uifc); 26857a229387SArnd Bergmann if (err) 26867a229387SArnd Bergmann return err; 26877a229387SArnd Bergmann 26887a229387SArnd Bergmann if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) 26897a229387SArnd Bergmann return -EFAULT; 26907a229387SArnd Bergmann 26917a229387SArnd Bergmann ifr = ifc.ifc_req; 26927a229387SArnd Bergmann ifr32 = compat_ptr(ifc32.ifcbuf); 26937a229387SArnd Bergmann for (i = 0, j = 0; 26946b96018bSArnd Bergmann i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len; 26956b96018bSArnd Bergmann i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) { 26966b96018bSArnd Bergmann if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq))) 26977a229387SArnd Bergmann return -EFAULT; 26987a229387SArnd Bergmann ifr32++; 26997a229387SArnd Bergmann ifr++; 27007a229387SArnd Bergmann } 27017a229387SArnd Bergmann 27027a229387SArnd Bergmann if (ifc32.ifcbuf == 0) { 27037a229387SArnd Bergmann /* Translate from 64-bit structure multiple to 27047a229387SArnd Bergmann * a 32-bit one. 27057a229387SArnd Bergmann */ 27067a229387SArnd Bergmann i = ifc.ifc_len; 27076b96018bSArnd Bergmann i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq)); 27087a229387SArnd Bergmann ifc32.ifc_len = i; 27097a229387SArnd Bergmann } else { 27107a229387SArnd Bergmann ifc32.ifc_len = i; 27117a229387SArnd Bergmann } 27126b96018bSArnd Bergmann if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) 27137a229387SArnd Bergmann return -EFAULT; 27147a229387SArnd Bergmann 27157a229387SArnd Bergmann return 0; 27167a229387SArnd Bergmann } 27177a229387SArnd Bergmann 27186b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) 27197a229387SArnd Bergmann { 27203a7da39dSBen Hutchings struct compat_ethtool_rxnfc __user *compat_rxnfc; 27213a7da39dSBen Hutchings bool convert_in = false, convert_out = false; 27223a7da39dSBen Hutchings size_t buf_size = ALIGN(sizeof(struct ifreq), 8); 27233a7da39dSBen Hutchings struct ethtool_rxnfc __user *rxnfc; 27247a229387SArnd Bergmann struct ifreq __user *ifr; 27253a7da39dSBen Hutchings u32 rule_cnt = 0, actual_rule_cnt; 27263a7da39dSBen Hutchings u32 ethcmd; 27277a229387SArnd Bergmann u32 data; 27283a7da39dSBen Hutchings int ret; 27297a229387SArnd Bergmann 27307a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 27317a229387SArnd Bergmann return -EFAULT; 27327a229387SArnd Bergmann 27333a7da39dSBen Hutchings compat_rxnfc = compat_ptr(data); 27343a7da39dSBen Hutchings 27353a7da39dSBen Hutchings if (get_user(ethcmd, &compat_rxnfc->cmd)) 27367a229387SArnd Bergmann return -EFAULT; 27377a229387SArnd Bergmann 27383a7da39dSBen Hutchings /* Most ethtool structures are defined without padding. 27393a7da39dSBen Hutchings * Unfortunately struct ethtool_rxnfc is an exception. 27403a7da39dSBen Hutchings */ 27413a7da39dSBen Hutchings switch (ethcmd) { 27423a7da39dSBen Hutchings default: 27433a7da39dSBen Hutchings break; 27443a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLALL: 27453a7da39dSBen Hutchings /* Buffer size is variable */ 27463a7da39dSBen Hutchings if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) 27473a7da39dSBen Hutchings return -EFAULT; 27483a7da39dSBen Hutchings if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) 27493a7da39dSBen Hutchings return -ENOMEM; 27503a7da39dSBen Hutchings buf_size += rule_cnt * sizeof(u32); 27513a7da39dSBen Hutchings /* fall through */ 27523a7da39dSBen Hutchings case ETHTOOL_GRXRINGS: 27533a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLCNT: 27543a7da39dSBen Hutchings case ETHTOOL_GRXCLSRULE: 275555664f32SBen Hutchings case ETHTOOL_SRXCLSRLINS: 27563a7da39dSBen Hutchings convert_out = true; 27573a7da39dSBen Hutchings /* fall through */ 27583a7da39dSBen Hutchings case ETHTOOL_SRXCLSRLDEL: 27593a7da39dSBen Hutchings buf_size += sizeof(struct ethtool_rxnfc); 27603a7da39dSBen Hutchings convert_in = true; 27613a7da39dSBen Hutchings break; 27623a7da39dSBen Hutchings } 27633a7da39dSBen Hutchings 27643a7da39dSBen Hutchings ifr = compat_alloc_user_space(buf_size); 2765954b1244SStephen Hemminger rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8); 27663a7da39dSBen Hutchings 27673a7da39dSBen Hutchings if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 27683a7da39dSBen Hutchings return -EFAULT; 27693a7da39dSBen Hutchings 27703a7da39dSBen Hutchings if (put_user(convert_in ? rxnfc : compat_ptr(data), 27713a7da39dSBen Hutchings &ifr->ifr_ifru.ifru_data)) 27723a7da39dSBen Hutchings return -EFAULT; 27733a7da39dSBen Hutchings 27743a7da39dSBen Hutchings if (convert_in) { 2775127fe533SAlexander Duyck /* We expect there to be holes between fs.m_ext and 27763a7da39dSBen Hutchings * fs.ring_cookie and at the end of fs, but nowhere else. 27773a7da39dSBen Hutchings */ 2778127fe533SAlexander Duyck BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + 2779127fe533SAlexander Duyck sizeof(compat_rxnfc->fs.m_ext) != 2780127fe533SAlexander Duyck offsetof(struct ethtool_rxnfc, fs.m_ext) + 2781127fe533SAlexander Duyck sizeof(rxnfc->fs.m_ext)); 27823a7da39dSBen Hutchings BUILD_BUG_ON( 27833a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.location) - 27843a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != 27853a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.location) - 27863a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.ring_cookie)); 27873a7da39dSBen Hutchings 27883a7da39dSBen Hutchings if (copy_in_user(rxnfc, compat_rxnfc, 2789954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.m_ext + 1) - 2790954b1244SStephen Hemminger (void __user *)rxnfc) || 27913a7da39dSBen Hutchings copy_in_user(&rxnfc->fs.ring_cookie, 27923a7da39dSBen Hutchings &compat_rxnfc->fs.ring_cookie, 2793954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.location + 1) - 2794954b1244SStephen Hemminger (void __user *)&rxnfc->fs.ring_cookie) || 27953a7da39dSBen Hutchings copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt, 27963a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 27973a7da39dSBen Hutchings return -EFAULT; 27983a7da39dSBen Hutchings } 27993a7da39dSBen Hutchings 28003a7da39dSBen Hutchings ret = dev_ioctl(net, SIOCETHTOOL, ifr); 28013a7da39dSBen Hutchings if (ret) 28023a7da39dSBen Hutchings return ret; 28033a7da39dSBen Hutchings 28043a7da39dSBen Hutchings if (convert_out) { 28053a7da39dSBen Hutchings if (copy_in_user(compat_rxnfc, rxnfc, 2806954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.m_ext + 1) - 2807954b1244SStephen Hemminger (const void __user *)rxnfc) || 28083a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->fs.ring_cookie, 28093a7da39dSBen Hutchings &rxnfc->fs.ring_cookie, 2810954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.location + 1) - 2811954b1244SStephen Hemminger (const void __user *)&rxnfc->fs.ring_cookie) || 28123a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, 28133a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 28143a7da39dSBen Hutchings return -EFAULT; 28153a7da39dSBen Hutchings 28163a7da39dSBen Hutchings if (ethcmd == ETHTOOL_GRXCLSRLALL) { 28173a7da39dSBen Hutchings /* As an optimisation, we only copy the actual 28183a7da39dSBen Hutchings * number of rules that the underlying 28193a7da39dSBen Hutchings * function returned. Since Mallory might 28203a7da39dSBen Hutchings * change the rule count in user memory, we 28213a7da39dSBen Hutchings * check that it is less than the rule count 28223a7da39dSBen Hutchings * originally given (as the user buffer size), 28233a7da39dSBen Hutchings * which has been range-checked. 28243a7da39dSBen Hutchings */ 28253a7da39dSBen Hutchings if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) 28263a7da39dSBen Hutchings return -EFAULT; 28273a7da39dSBen Hutchings if (actual_rule_cnt < rule_cnt) 28283a7da39dSBen Hutchings rule_cnt = actual_rule_cnt; 28293a7da39dSBen Hutchings if (copy_in_user(&compat_rxnfc->rule_locs[0], 28303a7da39dSBen Hutchings &rxnfc->rule_locs[0], 28313a7da39dSBen Hutchings rule_cnt * sizeof(u32))) 28323a7da39dSBen Hutchings return -EFAULT; 28333a7da39dSBen Hutchings } 28343a7da39dSBen Hutchings } 28353a7da39dSBen Hutchings 28363a7da39dSBen Hutchings return 0; 28377a229387SArnd Bergmann } 28387a229387SArnd Bergmann 28397a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) 28407a50a240SArnd Bergmann { 28417a50a240SArnd Bergmann void __user *uptr; 28427a50a240SArnd Bergmann compat_uptr_t uptr32; 28437a50a240SArnd Bergmann struct ifreq __user *uifr; 28447a50a240SArnd Bergmann 28457a50a240SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 28467a50a240SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 28477a50a240SArnd Bergmann return -EFAULT; 28487a50a240SArnd Bergmann 28497a50a240SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) 28507a50a240SArnd Bergmann return -EFAULT; 28517a50a240SArnd Bergmann 28527a50a240SArnd Bergmann uptr = compat_ptr(uptr32); 28537a50a240SArnd Bergmann 28547a50a240SArnd Bergmann if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc)) 28557a50a240SArnd Bergmann return -EFAULT; 28567a50a240SArnd Bergmann 28577a50a240SArnd Bergmann return dev_ioctl(net, SIOCWANDEV, uifr); 28587a50a240SArnd Bergmann } 28597a50a240SArnd Bergmann 28606b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd, 28616b96018bSArnd Bergmann struct compat_ifreq __user *ifr32) 28627a229387SArnd Bergmann { 28637a229387SArnd Bergmann struct ifreq kifr; 28647a229387SArnd Bergmann mm_segment_t old_fs; 28657a229387SArnd Bergmann int err; 28667a229387SArnd Bergmann 28677a229387SArnd Bergmann switch (cmd) { 28687a229387SArnd Bergmann case SIOCBONDENSLAVE: 28697a229387SArnd Bergmann case SIOCBONDRELEASE: 28707a229387SArnd Bergmann case SIOCBONDSETHWADDR: 28717a229387SArnd Bergmann case SIOCBONDCHANGEACTIVE: 28726b96018bSArnd Bergmann if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq))) 28737a229387SArnd Bergmann return -EFAULT; 28747a229387SArnd Bergmann 28757a229387SArnd Bergmann old_fs = get_fs(); 28767a229387SArnd Bergmann set_fs(KERNEL_DS); 2877c3f52ae6Sstephen hemminger err = dev_ioctl(net, cmd, 2878c3f52ae6Sstephen hemminger (struct ifreq __user __force *) &kifr); 28797a229387SArnd Bergmann set_fs(old_fs); 28807a229387SArnd Bergmann 28817a229387SArnd Bergmann return err; 28827a229387SArnd Bergmann default: 288307d106d0SLinus Torvalds return -ENOIOCTLCMD; 2884ccbd6a5aSJoe Perches } 28857a229387SArnd Bergmann } 28867a229387SArnd Bergmann 2887590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ 2888590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, 28896b96018bSArnd Bergmann struct compat_ifreq __user *u_ifreq32) 28907a229387SArnd Bergmann { 28917a229387SArnd Bergmann struct ifreq __user *u_ifreq64; 28927a229387SArnd Bergmann char tmp_buf[IFNAMSIZ]; 28937a229387SArnd Bergmann void __user *data64; 28947a229387SArnd Bergmann u32 data32; 28957a229387SArnd Bergmann 28967a229387SArnd Bergmann if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), 28977a229387SArnd Bergmann IFNAMSIZ)) 28987a229387SArnd Bergmann return -EFAULT; 2899417c3522SBen Hutchings if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) 29007a229387SArnd Bergmann return -EFAULT; 29017a229387SArnd Bergmann data64 = compat_ptr(data32); 29027a229387SArnd Bergmann 29037a229387SArnd Bergmann u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); 29047a229387SArnd Bergmann 29057a229387SArnd Bergmann if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], 29067a229387SArnd Bergmann IFNAMSIZ)) 29077a229387SArnd Bergmann return -EFAULT; 2908417c3522SBen Hutchings if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) 29097a229387SArnd Bergmann return -EFAULT; 29107a229387SArnd Bergmann 29116b96018bSArnd Bergmann return dev_ioctl(net, cmd, u_ifreq64); 29127a229387SArnd Bergmann } 29137a229387SArnd Bergmann 29146b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock, 29156b96018bSArnd Bergmann unsigned int cmd, struct compat_ifreq __user *uifr32) 29167a229387SArnd Bergmann { 2917a2116ed2SArnd Bergmann struct ifreq __user *uifr; 29187a229387SArnd Bergmann int err; 29197a229387SArnd Bergmann 2920a2116ed2SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 2921a2116ed2SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(*uifr32))) 29227a229387SArnd Bergmann return -EFAULT; 2923a2116ed2SArnd Bergmann 2924a2116ed2SArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr); 2925a2116ed2SArnd Bergmann 29267a229387SArnd Bergmann if (!err) { 29277a229387SArnd Bergmann switch (cmd) { 29287a229387SArnd Bergmann case SIOCGIFFLAGS: 29297a229387SArnd Bergmann case SIOCGIFMETRIC: 29307a229387SArnd Bergmann case SIOCGIFMTU: 29317a229387SArnd Bergmann case SIOCGIFMEM: 29327a229387SArnd Bergmann case SIOCGIFHWADDR: 29337a229387SArnd Bergmann case SIOCGIFINDEX: 29347a229387SArnd Bergmann case SIOCGIFADDR: 29357a229387SArnd Bergmann case SIOCGIFBRDADDR: 29367a229387SArnd Bergmann case SIOCGIFDSTADDR: 29377a229387SArnd Bergmann case SIOCGIFNETMASK: 2938fab2532bSArnd Bergmann case SIOCGIFPFLAGS: 29397a229387SArnd Bergmann case SIOCGIFTXQLEN: 2940fab2532bSArnd Bergmann case SIOCGMIIPHY: 2941fab2532bSArnd Bergmann case SIOCGMIIREG: 2942a2116ed2SArnd Bergmann if (copy_in_user(uifr32, uifr, sizeof(*uifr32))) 2943a2116ed2SArnd Bergmann err = -EFAULT; 29447a229387SArnd Bergmann break; 2945a2116ed2SArnd Bergmann } 2946a2116ed2SArnd Bergmann } 2947a2116ed2SArnd Bergmann return err; 2948a2116ed2SArnd Bergmann } 2949a2116ed2SArnd Bergmann 2950a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 2951a2116ed2SArnd Bergmann struct compat_ifreq __user *uifr32) 2952a2116ed2SArnd Bergmann { 2953a2116ed2SArnd Bergmann struct ifreq ifr; 2954a2116ed2SArnd Bergmann struct compat_ifmap __user *uifmap32; 2955a2116ed2SArnd Bergmann mm_segment_t old_fs; 2956a2116ed2SArnd Bergmann int err; 2957a2116ed2SArnd Bergmann 2958a2116ed2SArnd Bergmann uifmap32 = &uifr32->ifr_ifru.ifru_map; 2959a2116ed2SArnd Bergmann err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); 29603ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 29613ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 29623ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 29633ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.irq, &uifmap32->irq); 29643ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.dma, &uifmap32->dma); 29653ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.port, &uifmap32->port); 2966a2116ed2SArnd Bergmann if (err) 2967a2116ed2SArnd Bergmann return -EFAULT; 2968a2116ed2SArnd Bergmann 2969a2116ed2SArnd Bergmann old_fs = get_fs(); 2970a2116ed2SArnd Bergmann set_fs(KERNEL_DS); 2971c3f52ae6Sstephen hemminger err = dev_ioctl(net, cmd, (void __user __force *)&ifr); 2972a2116ed2SArnd Bergmann set_fs(old_fs); 2973a2116ed2SArnd Bergmann 2974a2116ed2SArnd Bergmann if (cmd == SIOCGIFMAP && !err) { 29757a229387SArnd Bergmann err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); 29763ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 29773ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 29783ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 29793ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.irq, &uifmap32->irq); 29803ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.dma, &uifmap32->dma); 29813ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.port, &uifmap32->port); 29827a229387SArnd Bergmann if (err) 29837a229387SArnd Bergmann err = -EFAULT; 29847a229387SArnd Bergmann } 29857a229387SArnd Bergmann return err; 29867a229387SArnd Bergmann } 29877a229387SArnd Bergmann 29887a229387SArnd Bergmann struct rtentry32 { 29897a229387SArnd Bergmann u32 rt_pad1; 29907a229387SArnd Bergmann struct sockaddr rt_dst; /* target address */ 29917a229387SArnd Bergmann struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ 29927a229387SArnd Bergmann struct sockaddr rt_genmask; /* target network mask (IP) */ 29937a229387SArnd Bergmann unsigned short rt_flags; 29947a229387SArnd Bergmann short rt_pad2; 29957a229387SArnd Bergmann u32 rt_pad3; 29967a229387SArnd Bergmann unsigned char rt_tos; 29977a229387SArnd Bergmann unsigned char rt_class; 29987a229387SArnd Bergmann short rt_pad4; 29997a229387SArnd Bergmann short rt_metric; /* +1 for binary compatibility! */ 30007a229387SArnd Bergmann /* char * */ u32 rt_dev; /* forcing the device at add */ 30017a229387SArnd Bergmann u32 rt_mtu; /* per route MTU/Window */ 30027a229387SArnd Bergmann u32 rt_window; /* Window clamping */ 30037a229387SArnd Bergmann unsigned short rt_irtt; /* Initial RTT */ 30047a229387SArnd Bergmann }; 30057a229387SArnd Bergmann 30067a229387SArnd Bergmann struct in6_rtmsg32 { 30077a229387SArnd Bergmann struct in6_addr rtmsg_dst; 30087a229387SArnd Bergmann struct in6_addr rtmsg_src; 30097a229387SArnd Bergmann struct in6_addr rtmsg_gateway; 30107a229387SArnd Bergmann u32 rtmsg_type; 30117a229387SArnd Bergmann u16 rtmsg_dst_len; 30127a229387SArnd Bergmann u16 rtmsg_src_len; 30137a229387SArnd Bergmann u32 rtmsg_metric; 30147a229387SArnd Bergmann u32 rtmsg_info; 30157a229387SArnd Bergmann u32 rtmsg_flags; 30167a229387SArnd Bergmann s32 rtmsg_ifindex; 30177a229387SArnd Bergmann }; 30187a229387SArnd Bergmann 30196b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock, 30206b96018bSArnd Bergmann unsigned int cmd, void __user *argp) 30217a229387SArnd Bergmann { 30227a229387SArnd Bergmann int ret; 30237a229387SArnd Bergmann void *r = NULL; 30247a229387SArnd Bergmann struct in6_rtmsg r6; 30257a229387SArnd Bergmann struct rtentry r4; 30267a229387SArnd Bergmann char devname[16]; 30277a229387SArnd Bergmann u32 rtdev; 30287a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 30297a229387SArnd Bergmann 30306b96018bSArnd Bergmann if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */ 30316b96018bSArnd Bergmann struct in6_rtmsg32 __user *ur6 = argp; 30327a229387SArnd Bergmann ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst), 30337a229387SArnd Bergmann 3 * sizeof(struct in6_addr)); 30343ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type)); 30353ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); 30363ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); 30373ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric)); 30383ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info)); 30393ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags)); 30403ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); 30417a229387SArnd Bergmann 30427a229387SArnd Bergmann r = (void *) &r6; 30437a229387SArnd Bergmann } else { /* ipv4 */ 30446b96018bSArnd Bergmann struct rtentry32 __user *ur4 = argp; 30457a229387SArnd Bergmann ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst), 30467a229387SArnd Bergmann 3 * sizeof(struct sockaddr)); 30473ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_flags, &(ur4->rt_flags)); 30483ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_metric, &(ur4->rt_metric)); 30493ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu)); 30503ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_window, &(ur4->rt_window)); 30513ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt)); 30523ddc5b46SMathieu Desnoyers ret |= get_user(rtdev, &(ur4->rt_dev)); 30537a229387SArnd Bergmann if (rtdev) { 30547a229387SArnd Bergmann ret |= copy_from_user(devname, compat_ptr(rtdev), 15); 3055c3f52ae6Sstephen hemminger r4.rt_dev = (char __user __force *)devname; 3056c3f52ae6Sstephen hemminger devname[15] = 0; 30577a229387SArnd Bergmann } else 30587a229387SArnd Bergmann r4.rt_dev = NULL; 30597a229387SArnd Bergmann 30607a229387SArnd Bergmann r = (void *) &r4; 30617a229387SArnd Bergmann } 30627a229387SArnd Bergmann 30637a229387SArnd Bergmann if (ret) { 30647a229387SArnd Bergmann ret = -EFAULT; 30657a229387SArnd Bergmann goto out; 30667a229387SArnd Bergmann } 30677a229387SArnd Bergmann 30687a229387SArnd Bergmann set_fs(KERNEL_DS); 30696b96018bSArnd Bergmann ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); 30707a229387SArnd Bergmann set_fs(old_fs); 30717a229387SArnd Bergmann 30727a229387SArnd Bergmann out: 30737a229387SArnd Bergmann return ret; 30747a229387SArnd Bergmann } 30757a229387SArnd Bergmann 30767a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE 30777a229387SArnd Bergmann * for some operations; this forces use of the newer bridge-utils that 307825985edcSLucas De Marchi * use compatible ioctls 30797a229387SArnd Bergmann */ 30806b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp) 30817a229387SArnd Bergmann { 30826b96018bSArnd Bergmann compat_ulong_t tmp; 30837a229387SArnd Bergmann 30846b96018bSArnd Bergmann if (get_user(tmp, argp)) 30857a229387SArnd Bergmann return -EFAULT; 30867a229387SArnd Bergmann if (tmp == BRCTL_GET_VERSION) 30877a229387SArnd Bergmann return BRCTL_VERSION + 1; 30887a229387SArnd Bergmann return -EINVAL; 30897a229387SArnd Bergmann } 30907a229387SArnd Bergmann 30916b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, 30926b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 30936b96018bSArnd Bergmann { 30946b96018bSArnd Bergmann void __user *argp = compat_ptr(arg); 30956b96018bSArnd Bergmann struct sock *sk = sock->sk; 30966b96018bSArnd Bergmann struct net *net = sock_net(sk); 30977a229387SArnd Bergmann 30986b96018bSArnd Bergmann if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 3099590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 31007a229387SArnd Bergmann 31016b96018bSArnd Bergmann switch (cmd) { 31026b96018bSArnd Bergmann case SIOCSIFBR: 31036b96018bSArnd Bergmann case SIOCGIFBR: 31046b96018bSArnd Bergmann return old_bridge_ioctl(argp); 31056b96018bSArnd Bergmann case SIOCGIFNAME: 31066b96018bSArnd Bergmann return dev_ifname32(net, argp); 31076b96018bSArnd Bergmann case SIOCGIFCONF: 31086b96018bSArnd Bergmann return dev_ifconf(net, argp); 31096b96018bSArnd Bergmann case SIOCETHTOOL: 31106b96018bSArnd Bergmann return ethtool_ioctl(net, argp); 31117a50a240SArnd Bergmann case SIOCWANDEV: 31127a50a240SArnd Bergmann return compat_siocwandev(net, argp); 3113a2116ed2SArnd Bergmann case SIOCGIFMAP: 3114a2116ed2SArnd Bergmann case SIOCSIFMAP: 3115a2116ed2SArnd Bergmann return compat_sioc_ifmap(net, cmd, argp); 31166b96018bSArnd Bergmann case SIOCBONDENSLAVE: 31176b96018bSArnd Bergmann case SIOCBONDRELEASE: 31186b96018bSArnd Bergmann case SIOCBONDSETHWADDR: 31196b96018bSArnd Bergmann case SIOCBONDCHANGEACTIVE: 31206b96018bSArnd Bergmann return bond_ioctl(net, cmd, argp); 31216b96018bSArnd Bergmann case SIOCADDRT: 31226b96018bSArnd Bergmann case SIOCDELRT: 31236b96018bSArnd Bergmann return routing_ioctl(net, sock, cmd, argp); 31246b96018bSArnd Bergmann case SIOCGSTAMP: 31256b96018bSArnd Bergmann return do_siocgstamp(net, sock, cmd, argp); 31266b96018bSArnd Bergmann case SIOCGSTAMPNS: 31276b96018bSArnd Bergmann return do_siocgstampns(net, sock, cmd, argp); 3128590d4693SBen Hutchings case SIOCBONDSLAVEINFOQUERY: 3129590d4693SBen Hutchings case SIOCBONDINFOQUERY: 3130a2116ed2SArnd Bergmann case SIOCSHWTSTAMP: 3131fd468c74SBen Hutchings case SIOCGHWTSTAMP: 3132590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 31337a229387SArnd Bergmann 31346b96018bSArnd Bergmann case FIOSETOWN: 31356b96018bSArnd Bergmann case SIOCSPGRP: 31366b96018bSArnd Bergmann case FIOGETOWN: 31376b96018bSArnd Bergmann case SIOCGPGRP: 31386b96018bSArnd Bergmann case SIOCBRADDBR: 31396b96018bSArnd Bergmann case SIOCBRDELBR: 31406b96018bSArnd Bergmann case SIOCGIFVLAN: 31416b96018bSArnd Bergmann case SIOCSIFVLAN: 31426b96018bSArnd Bergmann case SIOCADDDLCI: 31436b96018bSArnd Bergmann case SIOCDELDLCI: 3144c62cce2cSAndrey Vagin case SIOCGSKNS: 31456b96018bSArnd Bergmann return sock_ioctl(file, cmd, arg); 31466b96018bSArnd Bergmann 31476b96018bSArnd Bergmann case SIOCGIFFLAGS: 31486b96018bSArnd Bergmann case SIOCSIFFLAGS: 31496b96018bSArnd Bergmann case SIOCGIFMETRIC: 31506b96018bSArnd Bergmann case SIOCSIFMETRIC: 31516b96018bSArnd Bergmann case SIOCGIFMTU: 31526b96018bSArnd Bergmann case SIOCSIFMTU: 31536b96018bSArnd Bergmann case SIOCGIFMEM: 31546b96018bSArnd Bergmann case SIOCSIFMEM: 31556b96018bSArnd Bergmann case SIOCGIFHWADDR: 31566b96018bSArnd Bergmann case SIOCSIFHWADDR: 31576b96018bSArnd Bergmann case SIOCADDMULTI: 31586b96018bSArnd Bergmann case SIOCDELMULTI: 31596b96018bSArnd Bergmann case SIOCGIFINDEX: 31606b96018bSArnd Bergmann case SIOCGIFADDR: 31616b96018bSArnd Bergmann case SIOCSIFADDR: 31626b96018bSArnd Bergmann case SIOCSIFHWBROADCAST: 31636b96018bSArnd Bergmann case SIOCDIFADDR: 31646b96018bSArnd Bergmann case SIOCGIFBRDADDR: 31656b96018bSArnd Bergmann case SIOCSIFBRDADDR: 31666b96018bSArnd Bergmann case SIOCGIFDSTADDR: 31676b96018bSArnd Bergmann case SIOCSIFDSTADDR: 31686b96018bSArnd Bergmann case SIOCGIFNETMASK: 31696b96018bSArnd Bergmann case SIOCSIFNETMASK: 31706b96018bSArnd Bergmann case SIOCSIFPFLAGS: 31716b96018bSArnd Bergmann case SIOCGIFPFLAGS: 31726b96018bSArnd Bergmann case SIOCGIFTXQLEN: 31736b96018bSArnd Bergmann case SIOCSIFTXQLEN: 31746b96018bSArnd Bergmann case SIOCBRADDIF: 31756b96018bSArnd Bergmann case SIOCBRDELIF: 31769177efd3SArnd Bergmann case SIOCSIFNAME: 31779177efd3SArnd Bergmann case SIOCGMIIPHY: 31789177efd3SArnd Bergmann case SIOCGMIIREG: 31799177efd3SArnd Bergmann case SIOCSMIIREG: 31806b96018bSArnd Bergmann return dev_ifsioc(net, sock, cmd, argp); 31819177efd3SArnd Bergmann 31826b96018bSArnd Bergmann case SIOCSARP: 31836b96018bSArnd Bergmann case SIOCGARP: 31846b96018bSArnd Bergmann case SIOCDARP: 31856b96018bSArnd Bergmann case SIOCATMARK: 31869177efd3SArnd Bergmann return sock_do_ioctl(net, sock, cmd, arg); 31879177efd3SArnd Bergmann } 31889177efd3SArnd Bergmann 31896b96018bSArnd Bergmann return -ENOIOCTLCMD; 31906b96018bSArnd Bergmann } 31917a229387SArnd Bergmann 319295c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd, 319389bbfc95SShaun Pereira unsigned long arg) 319489bbfc95SShaun Pereira { 319589bbfc95SShaun Pereira struct socket *sock = file->private_data; 319689bbfc95SShaun Pereira int ret = -ENOIOCTLCMD; 319787de87d5SDavid S. Miller struct sock *sk; 319887de87d5SDavid S. Miller struct net *net; 319987de87d5SDavid S. Miller 320087de87d5SDavid S. Miller sk = sock->sk; 320187de87d5SDavid S. Miller net = sock_net(sk); 320289bbfc95SShaun Pereira 320389bbfc95SShaun Pereira if (sock->ops->compat_ioctl) 320489bbfc95SShaun Pereira ret = sock->ops->compat_ioctl(sock, cmd, arg); 320589bbfc95SShaun Pereira 320687de87d5SDavid S. Miller if (ret == -ENOIOCTLCMD && 320787de87d5SDavid S. Miller (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) 320887de87d5SDavid S. Miller ret = compat_wext_handle_ioctl(net, cmd, arg); 320987de87d5SDavid S. Miller 32106b96018bSArnd Bergmann if (ret == -ENOIOCTLCMD) 32116b96018bSArnd Bergmann ret = compat_sock_ioctl_trans(file, sock, cmd, arg); 32126b96018bSArnd Bergmann 321389bbfc95SShaun Pereira return ret; 321489bbfc95SShaun Pereira } 321589bbfc95SShaun Pereira #endif 321689bbfc95SShaun Pereira 3217ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) 3218ac5a488eSSridhar Samudrala { 3219ac5a488eSSridhar Samudrala return sock->ops->bind(sock, addr, addrlen); 3220ac5a488eSSridhar Samudrala } 3221c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind); 3222ac5a488eSSridhar Samudrala 3223ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog) 3224ac5a488eSSridhar Samudrala { 3225ac5a488eSSridhar Samudrala return sock->ops->listen(sock, backlog); 3226ac5a488eSSridhar Samudrala } 3227c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen); 3228ac5a488eSSridhar Samudrala 3229ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags) 3230ac5a488eSSridhar Samudrala { 3231ac5a488eSSridhar Samudrala struct sock *sk = sock->sk; 3232ac5a488eSSridhar Samudrala int err; 3233ac5a488eSSridhar Samudrala 3234ac5a488eSSridhar Samudrala err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, 3235ac5a488eSSridhar Samudrala newsock); 3236ac5a488eSSridhar Samudrala if (err < 0) 3237ac5a488eSSridhar Samudrala goto done; 3238ac5a488eSSridhar Samudrala 3239ac5a488eSSridhar Samudrala err = sock->ops->accept(sock, *newsock, flags); 3240ac5a488eSSridhar Samudrala if (err < 0) { 3241ac5a488eSSridhar Samudrala sock_release(*newsock); 3242fa8705b0STony Battersby *newsock = NULL; 3243ac5a488eSSridhar Samudrala goto done; 3244ac5a488eSSridhar Samudrala } 3245ac5a488eSSridhar Samudrala 3246ac5a488eSSridhar Samudrala (*newsock)->ops = sock->ops; 32471b08534eSWei Yongjun __module_get((*newsock)->ops->owner); 3248ac5a488eSSridhar Samudrala 3249ac5a488eSSridhar Samudrala done: 3250ac5a488eSSridhar Samudrala return err; 3251ac5a488eSSridhar Samudrala } 3252c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept); 3253ac5a488eSSridhar Samudrala 3254ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, 3255ac5a488eSSridhar Samudrala int flags) 3256ac5a488eSSridhar Samudrala { 3257ac5a488eSSridhar Samudrala return sock->ops->connect(sock, addr, addrlen, flags); 3258ac5a488eSSridhar Samudrala } 3259c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect); 3260ac5a488eSSridhar Samudrala 3261ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr, 3262ac5a488eSSridhar Samudrala int *addrlen) 3263ac5a488eSSridhar Samudrala { 3264ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 0); 3265ac5a488eSSridhar Samudrala } 3266c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname); 3267ac5a488eSSridhar Samudrala 3268ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr, 3269ac5a488eSSridhar Samudrala int *addrlen) 3270ac5a488eSSridhar Samudrala { 3271ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 1); 3272ac5a488eSSridhar Samudrala } 3273c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername); 3274ac5a488eSSridhar Samudrala 3275ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname, 3276ac5a488eSSridhar Samudrala char *optval, int *optlen) 3277ac5a488eSSridhar Samudrala { 3278ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3279fb8621bbSNamhyung Kim char __user *uoptval; 3280fb8621bbSNamhyung Kim int __user *uoptlen; 3281ac5a488eSSridhar Samudrala int err; 3282ac5a488eSSridhar Samudrala 3283fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3284fb8621bbSNamhyung Kim uoptlen = (int __user __force *) optlen; 3285fb8621bbSNamhyung Kim 3286ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3287ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3288fb8621bbSNamhyung Kim err = sock_getsockopt(sock, level, optname, uoptval, uoptlen); 3289ac5a488eSSridhar Samudrala else 3290fb8621bbSNamhyung Kim err = sock->ops->getsockopt(sock, level, optname, uoptval, 3291fb8621bbSNamhyung Kim uoptlen); 3292ac5a488eSSridhar Samudrala set_fs(oldfs); 3293ac5a488eSSridhar Samudrala return err; 3294ac5a488eSSridhar Samudrala } 3295c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt); 3296ac5a488eSSridhar Samudrala 3297ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname, 3298b7058842SDavid S. Miller char *optval, unsigned int optlen) 3299ac5a488eSSridhar Samudrala { 3300ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3301fb8621bbSNamhyung Kim char __user *uoptval; 3302ac5a488eSSridhar Samudrala int err; 3303ac5a488eSSridhar Samudrala 3304fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3305fb8621bbSNamhyung Kim 3306ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3307ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3308fb8621bbSNamhyung Kim err = sock_setsockopt(sock, level, optname, uoptval, optlen); 3309ac5a488eSSridhar Samudrala else 3310fb8621bbSNamhyung Kim err = sock->ops->setsockopt(sock, level, optname, uoptval, 3311ac5a488eSSridhar Samudrala optlen); 3312ac5a488eSSridhar Samudrala set_fs(oldfs); 3313ac5a488eSSridhar Samudrala return err; 3314ac5a488eSSridhar Samudrala } 3315c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt); 3316ac5a488eSSridhar Samudrala 3317ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset, 3318ac5a488eSSridhar Samudrala size_t size, int flags) 3319ac5a488eSSridhar Samudrala { 3320ac5a488eSSridhar Samudrala if (sock->ops->sendpage) 3321ac5a488eSSridhar Samudrala return sock->ops->sendpage(sock, page, offset, size, flags); 3322ac5a488eSSridhar Samudrala 3323ac5a488eSSridhar Samudrala return sock_no_sendpage(sock, page, offset, size, flags); 3324ac5a488eSSridhar Samudrala } 3325c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage); 3326ac5a488eSSridhar Samudrala 3327ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg) 3328ac5a488eSSridhar Samudrala { 3329ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3330ac5a488eSSridhar Samudrala int err; 3331ac5a488eSSridhar Samudrala 3332ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3333ac5a488eSSridhar Samudrala err = sock->ops->ioctl(sock, cmd, arg); 3334ac5a488eSSridhar Samudrala set_fs(oldfs); 3335ac5a488eSSridhar Samudrala 3336ac5a488eSSridhar Samudrala return err; 3337ac5a488eSSridhar Samudrala } 3338c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl); 3339ac5a488eSSridhar Samudrala 334091cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) 334191cf45f0STrond Myklebust { 334291cf45f0STrond Myklebust return sock->ops->shutdown(sock, how); 334391cf45f0STrond Myklebust } 334491cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown); 3345