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/wanrouter.h> 731da177e4SLinus Torvalds #include <linux/if_bridge.h> 7420380731SArnaldo Carvalho de Melo #include <linux/if_frad.h> 7520380731SArnaldo Carvalho de Melo #include <linux/if_vlan.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> 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds #include <asm/uaccess.h> 931da177e4SLinus Torvalds #include <asm/unistd.h> 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds #include <net/compat.h> 9687de87d5SDavid S. Miller #include <net/wext.h> 97f8451725SHerbert Xu #include <net/cls_cgroup.h> 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds #include <net/sock.h> 1001da177e4SLinus Torvalds #include <linux/netfilter.h> 1011da177e4SLinus Torvalds 1026b96018bSArnd Bergmann #include <linux/if_tun.h> 1036b96018bSArnd Bergmann #include <linux/ipv6_route.h> 1046b96018bSArnd Bergmann #include <linux/route.h> 1056b96018bSArnd Bergmann #include <linux/sockios.h> 1066b96018bSArnd Bergmann #include <linux/atalk.h> 1076b96018bSArnd Bergmann 1081da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare); 109027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, 110027445c3SBadari Pulavarty unsigned long nr_segs, loff_t pos); 111027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, 112027445c3SBadari Pulavarty unsigned long nr_segs, loff_t pos); 1131da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma); 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file); 1161da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, 1171da177e4SLinus Torvalds struct poll_table_struct *wait); 11889bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 11989bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 12089bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, 12189bbfc95SShaun Pereira unsigned int cmd, unsigned long arg); 12289bbfc95SShaun Pereira #endif 1231da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on); 1241da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page, 1251da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more); 1269c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 1279c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 1289c55e01cSJens Axboe unsigned int flags); 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds /* 1311da177e4SLinus Torvalds * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear 1321da177e4SLinus Torvalds * in the operation structures but are done directly via the socketcall() multiplexor. 1331da177e4SLinus Torvalds */ 1341da177e4SLinus Torvalds 135da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = { 1361da177e4SLinus Torvalds .owner = THIS_MODULE, 1371da177e4SLinus Torvalds .llseek = no_llseek, 1381da177e4SLinus Torvalds .aio_read = sock_aio_read, 1391da177e4SLinus Torvalds .aio_write = sock_aio_write, 1401da177e4SLinus Torvalds .poll = sock_poll, 1411da177e4SLinus Torvalds .unlocked_ioctl = sock_ioctl, 14289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 14389bbfc95SShaun Pereira .compat_ioctl = compat_sock_ioctl, 14489bbfc95SShaun Pereira #endif 1451da177e4SLinus Torvalds .mmap = sock_mmap, 1461da177e4SLinus Torvalds .open = sock_no_open, /* special open code to disallow open via /proc */ 1471da177e4SLinus Torvalds .release = sock_close, 1481da177e4SLinus Torvalds .fasync = sock_fasync, 1495274f052SJens Axboe .sendpage = sock_sendpage, 1505274f052SJens Axboe .splice_write = generic_splice_sendpage, 1519c55e01cSJens Axboe .splice_read = sock_splice_read, 1521da177e4SLinus Torvalds }; 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds /* 1551da177e4SLinus Torvalds * The protocol list. Each protocol is registered in here. 1561da177e4SLinus Torvalds */ 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock); 159190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds /* 1621da177e4SLinus Torvalds * Statistics counters of the socket lists 1631da177e4SLinus Torvalds */ 1641da177e4SLinus Torvalds 165c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use); 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds /* 16889bddce5SStephen Hemminger * Support routines. 16989bddce5SStephen Hemminger * Move socket addresses back and forth across the kernel/user 1701da177e4SLinus Torvalds * divide and look after the messy bits. 1711da177e4SLinus Torvalds */ 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds /** 1741da177e4SLinus Torvalds * move_addr_to_kernel - copy a socket address into kernel space 1751da177e4SLinus Torvalds * @uaddr: Address in user space 1761da177e4SLinus Torvalds * @kaddr: Address in kernel space 1771da177e4SLinus Torvalds * @ulen: Length in user space 1781da177e4SLinus Torvalds * 1791da177e4SLinus Torvalds * The address is copied into kernel space. If the provided address is 1801da177e4SLinus Torvalds * too long an error code of -EINVAL is returned. If the copy gives 1811da177e4SLinus Torvalds * invalid addresses -EFAULT is returned. On a success 0 is returned. 1821da177e4SLinus Torvalds */ 1831da177e4SLinus Torvalds 18443db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr) 1851da177e4SLinus Torvalds { 186230b1839SYOSHIFUJI Hideaki if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) 1871da177e4SLinus Torvalds return -EINVAL; 1881da177e4SLinus Torvalds if (ulen == 0) 1891da177e4SLinus Torvalds return 0; 1901da177e4SLinus Torvalds if (copy_from_user(kaddr, uaddr, ulen)) 1911da177e4SLinus Torvalds return -EFAULT; 1923ec3b2fbSDavid Woodhouse return audit_sockaddr(ulen, kaddr); 1931da177e4SLinus Torvalds } 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds /** 1961da177e4SLinus Torvalds * move_addr_to_user - copy an address to user space 1971da177e4SLinus Torvalds * @kaddr: kernel space address 1981da177e4SLinus Torvalds * @klen: length of address in kernel 1991da177e4SLinus Torvalds * @uaddr: user space address 2001da177e4SLinus Torvalds * @ulen: pointer to user length field 2011da177e4SLinus Torvalds * 2021da177e4SLinus Torvalds * The value pointed to by ulen on entry is the buffer length available. 2031da177e4SLinus Torvalds * This is overwritten with the buffer space used. -EINVAL is returned 2041da177e4SLinus Torvalds * if an overlong buffer is specified or a negative buffer size. -EFAULT 2051da177e4SLinus Torvalds * is returned if either the buffer or the length field are not 2061da177e4SLinus Torvalds * accessible. 2071da177e4SLinus Torvalds * After copying the data up to the limit the user specifies, the true 2081da177e4SLinus Torvalds * length of the data is written over the length limit the user 2091da177e4SLinus Torvalds * specified. Zero is returned for a success. 2101da177e4SLinus Torvalds */ 2111da177e4SLinus Torvalds 21243db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, 21311165f14Sstephen hemminger void __user *uaddr, int __user *ulen) 2141da177e4SLinus Torvalds { 2151da177e4SLinus Torvalds int err; 2161da177e4SLinus Torvalds int len; 2171da177e4SLinus Torvalds 21889bddce5SStephen Hemminger err = get_user(len, ulen); 21989bddce5SStephen Hemminger if (err) 2201da177e4SLinus Torvalds return err; 2211da177e4SLinus Torvalds if (len > klen) 2221da177e4SLinus Torvalds len = klen; 223230b1839SYOSHIFUJI Hideaki if (len < 0 || len > sizeof(struct sockaddr_storage)) 2241da177e4SLinus Torvalds return -EINVAL; 22589bddce5SStephen Hemminger if (len) { 226d6fe3945SSteve Grubb if (audit_sockaddr(klen, kaddr)) 227d6fe3945SSteve Grubb return -ENOMEM; 2281da177e4SLinus Torvalds if (copy_to_user(uaddr, kaddr, len)) 2291da177e4SLinus Torvalds return -EFAULT; 2301da177e4SLinus Torvalds } 2311da177e4SLinus Torvalds /* 2321da177e4SLinus Torvalds * "fromlen shall refer to the value before truncation.." 2331da177e4SLinus Torvalds * 1003.1g 2341da177e4SLinus Torvalds */ 2351da177e4SLinus Torvalds return __put_user(klen, ulen); 2361da177e4SLinus Torvalds } 2371da177e4SLinus Torvalds 238e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly; 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb) 2411da177e4SLinus Torvalds { 2421da177e4SLinus Torvalds struct socket_alloc *ei; 243eaefd110SEric Dumazet struct socket_wq *wq; 24489bddce5SStephen Hemminger 245e94b1766SChristoph Lameter ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 2461da177e4SLinus Torvalds if (!ei) 2471da177e4SLinus Torvalds return NULL; 248eaefd110SEric Dumazet wq = kmalloc(sizeof(*wq), GFP_KERNEL); 249eaefd110SEric Dumazet if (!wq) { 25043815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 25143815482SEric Dumazet return NULL; 25243815482SEric Dumazet } 253eaefd110SEric Dumazet init_waitqueue_head(&wq->wait); 254eaefd110SEric Dumazet wq->fasync_list = NULL; 255eaefd110SEric Dumazet RCU_INIT_POINTER(ei->socket.wq, wq); 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds ei->socket.state = SS_UNCONNECTED; 2581da177e4SLinus Torvalds ei->socket.flags = 0; 2591da177e4SLinus Torvalds ei->socket.ops = NULL; 2601da177e4SLinus Torvalds ei->socket.sk = NULL; 2611da177e4SLinus Torvalds ei->socket.file = NULL; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds return &ei->vfs_inode; 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode) 2671da177e4SLinus Torvalds { 26843815482SEric Dumazet struct socket_alloc *ei; 269eaefd110SEric Dumazet struct socket_wq *wq; 27043815482SEric Dumazet 27143815482SEric Dumazet ei = container_of(inode, struct socket_alloc, vfs_inode); 272eaefd110SEric Dumazet wq = rcu_dereference_protected(ei->socket.wq, 1); 27361845220SLai Jiangshan kfree_rcu(wq, rcu); 27443815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds 27751cc5068SAlexey Dobriyan static void init_once(void *foo) 2781da177e4SLinus Torvalds { 2791da177e4SLinus Torvalds struct socket_alloc *ei = (struct socket_alloc *)foo; 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode); 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds static int init_inodecache(void) 2851da177e4SLinus Torvalds { 2861da177e4SLinus Torvalds sock_inode_cachep = kmem_cache_create("sock_inode_cache", 2871da177e4SLinus Torvalds sizeof(struct socket_alloc), 28889bddce5SStephen Hemminger 0, 28989bddce5SStephen Hemminger (SLAB_HWCACHE_ALIGN | 29089bddce5SStephen Hemminger SLAB_RECLAIM_ACCOUNT | 291fffb60f9SPaul Jackson SLAB_MEM_SPREAD), 29220c2df83SPaul Mundt init_once); 2931da177e4SLinus Torvalds if (sock_inode_cachep == NULL) 2941da177e4SLinus Torvalds return -ENOMEM; 2951da177e4SLinus Torvalds return 0; 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 298b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = { 2991da177e4SLinus Torvalds .alloc_inode = sock_alloc_inode, 3001da177e4SLinus Torvalds .destroy_inode = sock_destroy_inode, 3011da177e4SLinus Torvalds .statfs = simple_statfs, 3021da177e4SLinus Torvalds }; 3031da177e4SLinus Torvalds 304c23fbb6bSEric Dumazet /* 305c23fbb6bSEric Dumazet * sockfs_dname() is called from d_path(). 306c23fbb6bSEric Dumazet */ 307c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) 308c23fbb6bSEric Dumazet { 309c23fbb6bSEric Dumazet return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", 310c23fbb6bSEric Dumazet dentry->d_inode->i_ino); 311c23fbb6bSEric Dumazet } 312c23fbb6bSEric Dumazet 3133ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = { 314c23fbb6bSEric Dumazet .d_dname = sockfs_dname, 3151da177e4SLinus Torvalds }; 3161da177e4SLinus Torvalds 317c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type, 318c74a1cbbSAl Viro int flags, const char *dev_name, void *data) 319c74a1cbbSAl Viro { 320c74a1cbbSAl Viro return mount_pseudo(fs_type, "socket:", &sockfs_ops, 321c74a1cbbSAl Viro &sockfs_dentry_operations, SOCKFS_MAGIC); 322c74a1cbbSAl Viro } 323c74a1cbbSAl Viro 324c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly; 325c74a1cbbSAl Viro 326c74a1cbbSAl Viro static struct file_system_type sock_fs_type = { 327c74a1cbbSAl Viro .name = "sockfs", 328c74a1cbbSAl Viro .mount = sockfs_mount, 329c74a1cbbSAl Viro .kill_sb = kill_anon_super, 330c74a1cbbSAl Viro }; 331c74a1cbbSAl Viro 3321da177e4SLinus Torvalds /* 3331da177e4SLinus Torvalds * Obtains the first available file descriptor and sets it up for use. 3341da177e4SLinus Torvalds * 33539d8c1b6SDavid S. Miller * These functions create file structures and maps them to fd space 33639d8c1b6SDavid S. Miller * of the current process. On success it returns file descriptor 3371da177e4SLinus Torvalds * and file struct implicitly stored in sock->file. 3381da177e4SLinus Torvalds * Note that another thread may close file descriptor before we return 3391da177e4SLinus Torvalds * from this function. We use the fact that now we do not refer 3401da177e4SLinus Torvalds * to socket after mapping. If one day we will need it, this 3411da177e4SLinus Torvalds * function will increment ref. count on file by 1. 3421da177e4SLinus Torvalds * 3431da177e4SLinus Torvalds * In any case returned fd MAY BE not valid! 3441da177e4SLinus Torvalds * This race condition is unavoidable 3451da177e4SLinus Torvalds * with shared fd spaces, we cannot solve it inside kernel, 3461da177e4SLinus Torvalds * but we take care of internal coherence yet. 3471da177e4SLinus Torvalds */ 3481da177e4SLinus Torvalds 3497cbe66b6SAl Viro static int sock_alloc_file(struct socket *sock, struct file **f, int flags) 3501da177e4SLinus Torvalds { 3517cbe66b6SAl Viro struct qstr name = { .name = "" }; 3522c48b9c4SAl Viro struct path path; 3537cbe66b6SAl Viro struct file *file; 3541da177e4SLinus Torvalds int fd; 3551da177e4SLinus Torvalds 356a677a039SUlrich Drepper fd = get_unused_fd_flags(flags); 3577cbe66b6SAl Viro if (unlikely(fd < 0)) 3587cbe66b6SAl Viro return fd; 3591da177e4SLinus Torvalds 3604b936885SNick Piggin path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); 3612c48b9c4SAl Viro if (unlikely(!path.dentry)) { 3627cbe66b6SAl Viro put_unused_fd(fd); 36339d8c1b6SDavid S. Miller return -ENOMEM; 3647cbe66b6SAl Viro } 3652c48b9c4SAl Viro path.mnt = mntget(sock_mnt); 36639d8c1b6SDavid S. Miller 3672c48b9c4SAl Viro d_instantiate(path.dentry, SOCK_INODE(sock)); 368cc3808f8SAl Viro SOCK_INODE(sock)->i_fop = &socket_file_ops; 369cc3808f8SAl Viro 3702c48b9c4SAl Viro file = alloc_file(&path, FMODE_READ | FMODE_WRITE, 371cc3808f8SAl Viro &socket_file_ops); 372cc3808f8SAl Viro if (unlikely(!file)) { 373cc3808f8SAl Viro /* drop dentry, keep inode */ 3747de9c6eeSAl Viro ihold(path.dentry->d_inode); 3752c48b9c4SAl Viro path_put(&path); 376cc3808f8SAl Viro put_unused_fd(fd); 377cc3808f8SAl Viro return -ENFILE; 378cc3808f8SAl Viro } 3791da177e4SLinus Torvalds 3801da177e4SLinus Torvalds sock->file = file; 38177d27200SUlrich Drepper file->f_flags = O_RDWR | (flags & O_NONBLOCK); 3821da177e4SLinus Torvalds file->f_pos = 0; 38307dc3f07SBenjamin LaHaise file->private_data = sock; 38439d8c1b6SDavid S. Miller 3857cbe66b6SAl Viro *f = file; 3867cbe66b6SAl Viro return fd; 3871da177e4SLinus Torvalds } 3881da177e4SLinus Torvalds 389a677a039SUlrich Drepper int sock_map_fd(struct socket *sock, int flags) 39039d8c1b6SDavid S. Miller { 39139d8c1b6SDavid S. Miller struct file *newfile; 3927cbe66b6SAl Viro int fd = sock_alloc_file(sock, &newfile, flags); 39339d8c1b6SDavid S. Miller 3947cbe66b6SAl Viro if (likely(fd >= 0)) 39539d8c1b6SDavid S. Miller fd_install(fd, newfile); 3967cbe66b6SAl Viro 3971da177e4SLinus Torvalds return fd; 3981da177e4SLinus Torvalds } 399c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_map_fd); 4001da177e4SLinus Torvalds 401406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err) 4026cb153caSBenjamin LaHaise { 4036cb153caSBenjamin LaHaise if (file->f_op == &socket_file_ops) 4046cb153caSBenjamin LaHaise return file->private_data; /* set in sock_map_fd */ 4056cb153caSBenjamin LaHaise 4066cb153caSBenjamin LaHaise *err = -ENOTSOCK; 4076cb153caSBenjamin LaHaise return NULL; 4086cb153caSBenjamin LaHaise } 409406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file); 4106cb153caSBenjamin LaHaise 4111da177e4SLinus Torvalds /** 4121da177e4SLinus Torvalds * sockfd_lookup - Go from a file number to its socket slot 4131da177e4SLinus Torvalds * @fd: file handle 4141da177e4SLinus Torvalds * @err: pointer to an error code return 4151da177e4SLinus Torvalds * 4161da177e4SLinus Torvalds * The file handle passed in is locked and the socket it is bound 4171da177e4SLinus Torvalds * too is returned. If an error occurs the err pointer is overwritten 4181da177e4SLinus Torvalds * with a negative errno code and NULL is returned. The function checks 4191da177e4SLinus Torvalds * for both invalid handles and passing a handle which is not a socket. 4201da177e4SLinus Torvalds * 4211da177e4SLinus Torvalds * On a success the socket object pointer is returned. 4221da177e4SLinus Torvalds */ 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err) 4251da177e4SLinus Torvalds { 4261da177e4SLinus Torvalds struct file *file; 4271da177e4SLinus Torvalds struct socket *sock; 4281da177e4SLinus Torvalds 42989bddce5SStephen Hemminger file = fget(fd); 43089bddce5SStephen Hemminger if (!file) { 4311da177e4SLinus Torvalds *err = -EBADF; 4321da177e4SLinus Torvalds return NULL; 4331da177e4SLinus Torvalds } 43489bddce5SStephen Hemminger 4356cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4366cb153caSBenjamin LaHaise if (!sock) 4371da177e4SLinus Torvalds fput(file); 4386cb153caSBenjamin LaHaise return sock; 4391da177e4SLinus Torvalds } 440c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup); 4411da177e4SLinus Torvalds 4426cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) 4436cb153caSBenjamin LaHaise { 4446cb153caSBenjamin LaHaise struct file *file; 4456cb153caSBenjamin LaHaise struct socket *sock; 4466cb153caSBenjamin LaHaise 4473672558cSHua Zhong *err = -EBADF; 4486cb153caSBenjamin LaHaise file = fget_light(fd, fput_needed); 4496cb153caSBenjamin LaHaise if (file) { 4506cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4516cb153caSBenjamin LaHaise if (sock) 4521da177e4SLinus Torvalds return sock; 4536cb153caSBenjamin LaHaise fput_light(file, *fput_needed); 4546cb153caSBenjamin LaHaise } 4556cb153caSBenjamin LaHaise return NULL; 4561da177e4SLinus Torvalds } 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds /** 4591da177e4SLinus Torvalds * sock_alloc - allocate a socket 4601da177e4SLinus Torvalds * 4611da177e4SLinus Torvalds * Allocate a new inode and socket object. The two are bound together 4621da177e4SLinus Torvalds * and initialised. The socket is then returned. If we are out of inodes 4631da177e4SLinus Torvalds * NULL is returned. 4641da177e4SLinus Torvalds */ 4651da177e4SLinus Torvalds 4661da177e4SLinus Torvalds static struct socket *sock_alloc(void) 4671da177e4SLinus Torvalds { 4681da177e4SLinus Torvalds struct inode *inode; 4691da177e4SLinus Torvalds struct socket *sock; 4701da177e4SLinus Torvalds 471a209dfc7SEric Dumazet inode = new_inode_pseudo(sock_mnt->mnt_sb); 4721da177e4SLinus Torvalds if (!inode) 4731da177e4SLinus Torvalds return NULL; 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds sock = SOCKET_I(inode); 4761da177e4SLinus Torvalds 47729a020d3SEric Dumazet kmemcheck_annotate_bitfield(sock, type); 47885fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 4791da177e4SLinus Torvalds inode->i_mode = S_IFSOCK | S_IRWXUGO; 4808192b0c4SDavid Howells inode->i_uid = current_fsuid(); 4818192b0c4SDavid Howells inode->i_gid = current_fsgid(); 4821da177e4SLinus Torvalds 48319e8d69cSAlex Shi this_cpu_add(sockets_in_use, 1); 4841da177e4SLinus Torvalds return sock; 4851da177e4SLinus Torvalds } 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds /* 4881da177e4SLinus Torvalds * In theory you can't get an open on this inode, but /proc provides 4891da177e4SLinus Torvalds * a back door. Remember to keep it shut otherwise you'll let the 4901da177e4SLinus Torvalds * creepy crawlies in. 4911da177e4SLinus Torvalds */ 4921da177e4SLinus Torvalds 4931da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare) 4941da177e4SLinus Torvalds { 4951da177e4SLinus Torvalds return -ENXIO; 4961da177e4SLinus Torvalds } 4971da177e4SLinus Torvalds 4984b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = { 4991da177e4SLinus Torvalds .owner = THIS_MODULE, 5001da177e4SLinus Torvalds .open = sock_no_open, 5016038f373SArnd Bergmann .llseek = noop_llseek, 5021da177e4SLinus Torvalds }; 5031da177e4SLinus Torvalds 5041da177e4SLinus Torvalds /** 5051da177e4SLinus Torvalds * sock_release - close a socket 5061da177e4SLinus Torvalds * @sock: socket to close 5071da177e4SLinus Torvalds * 5081da177e4SLinus Torvalds * The socket is released from the protocol stack if it has a release 5091da177e4SLinus Torvalds * callback, and the inode is then released if the socket is bound to 5101da177e4SLinus Torvalds * an inode not a file. 5111da177e4SLinus Torvalds */ 5121da177e4SLinus Torvalds 5131da177e4SLinus Torvalds void sock_release(struct socket *sock) 5141da177e4SLinus Torvalds { 5151da177e4SLinus Torvalds if (sock->ops) { 5161da177e4SLinus Torvalds struct module *owner = sock->ops->owner; 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds sock->ops->release(sock); 5191da177e4SLinus Torvalds sock->ops = NULL; 5201da177e4SLinus Torvalds module_put(owner); 5211da177e4SLinus Torvalds } 5221da177e4SLinus Torvalds 523eaefd110SEric Dumazet if (rcu_dereference_protected(sock->wq, 1)->fasync_list) 5241da177e4SLinus Torvalds printk(KERN_ERR "sock_release: fasync list not empty!\n"); 5251da177e4SLinus Torvalds 526b09e786bSMikulas Patocka if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags)) 527b09e786bSMikulas Patocka return; 528b09e786bSMikulas Patocka 52919e8d69cSAlex Shi this_cpu_sub(sockets_in_use, 1); 5301da177e4SLinus Torvalds if (!sock->file) { 5311da177e4SLinus Torvalds iput(SOCK_INODE(sock)); 5321da177e4SLinus Torvalds return; 5331da177e4SLinus Torvalds } 5341da177e4SLinus Torvalds sock->file = NULL; 5351da177e4SLinus Torvalds } 536c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release); 5371da177e4SLinus Torvalds 5382244d07bSOliver Hartkopp int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) 53920d49473SPatrick Ohly { 5402244d07bSOliver Hartkopp *tx_flags = 0; 54120d49473SPatrick Ohly if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) 5422244d07bSOliver Hartkopp *tx_flags |= SKBTX_HW_TSTAMP; 54320d49473SPatrick Ohly if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) 5442244d07bSOliver Hartkopp *tx_flags |= SKBTX_SW_TSTAMP; 5456e3e939fSJohannes Berg if (sock_flag(sk, SOCK_WIFI_STATUS)) 5466e3e939fSJohannes Berg *tx_flags |= SKBTX_WIFI_STATUS; 54720d49473SPatrick Ohly return 0; 54820d49473SPatrick Ohly } 54920d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp); 55020d49473SPatrick Ohly 551228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock, 5521da177e4SLinus Torvalds struct msghdr *msg, size_t size) 5531da177e4SLinus Torvalds { 5541da177e4SLinus Torvalds struct sock_iocb *si = kiocb_to_siocb(iocb); 5551da177e4SLinus Torvalds 556f8451725SHerbert Xu sock_update_classid(sock->sk); 557f8451725SHerbert Xu 5581da177e4SLinus Torvalds si->sock = sock; 5591da177e4SLinus Torvalds si->scm = NULL; 5601da177e4SLinus Torvalds si->msg = msg; 5611da177e4SLinus Torvalds si->size = size; 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds return sock->ops->sendmsg(iocb, sock, msg, size); 5641da177e4SLinus Torvalds } 5651da177e4SLinus Torvalds 566228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, 567228e548eSAnton Blanchard struct msghdr *msg, size_t size) 568228e548eSAnton Blanchard { 569228e548eSAnton Blanchard int err = security_socket_sendmsg(sock, msg, size); 570228e548eSAnton Blanchard 571228e548eSAnton Blanchard return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size); 572228e548eSAnton Blanchard } 573228e548eSAnton Blanchard 5741da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) 5751da177e4SLinus Torvalds { 5761da177e4SLinus Torvalds struct kiocb iocb; 5771da177e4SLinus Torvalds struct sock_iocb siocb; 5781da177e4SLinus Torvalds int ret; 5791da177e4SLinus Torvalds 5801da177e4SLinus Torvalds init_sync_kiocb(&iocb, NULL); 5811da177e4SLinus Torvalds iocb.private = &siocb; 5821da177e4SLinus Torvalds ret = __sock_sendmsg(&iocb, sock, msg, size); 5831da177e4SLinus Torvalds if (-EIOCBQUEUED == ret) 5841da177e4SLinus Torvalds ret = wait_on_sync_kiocb(&iocb); 5851da177e4SLinus Torvalds return ret; 5861da177e4SLinus Torvalds } 587c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg); 5881da177e4SLinus Torvalds 589894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size) 590228e548eSAnton Blanchard { 591228e548eSAnton Blanchard struct kiocb iocb; 592228e548eSAnton Blanchard struct sock_iocb siocb; 593228e548eSAnton Blanchard int ret; 594228e548eSAnton Blanchard 595228e548eSAnton Blanchard init_sync_kiocb(&iocb, NULL); 596228e548eSAnton Blanchard iocb.private = &siocb; 597228e548eSAnton Blanchard ret = __sock_sendmsg_nosec(&iocb, sock, msg, size); 598228e548eSAnton Blanchard if (-EIOCBQUEUED == ret) 599228e548eSAnton Blanchard ret = wait_on_sync_kiocb(&iocb); 600228e548eSAnton Blanchard return ret; 601228e548eSAnton Blanchard } 602228e548eSAnton Blanchard 6031da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg, 6041da177e4SLinus Torvalds struct kvec *vec, size_t num, size_t size) 6051da177e4SLinus Torvalds { 6061da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 6071da177e4SLinus Torvalds int result; 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds set_fs(KERNEL_DS); 6101da177e4SLinus Torvalds /* 6111da177e4SLinus Torvalds * the following is safe, since for compiler definitions of kvec and 6121da177e4SLinus Torvalds * iovec are identical, yielding the same in-core layout and alignment 6131da177e4SLinus Torvalds */ 61489bddce5SStephen Hemminger msg->msg_iov = (struct iovec *)vec; 6151da177e4SLinus Torvalds msg->msg_iovlen = num; 6161da177e4SLinus Torvalds result = sock_sendmsg(sock, msg, size); 6171da177e4SLinus Torvalds set_fs(oldfs); 6181da177e4SLinus Torvalds return result; 6191da177e4SLinus Torvalds } 620c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg); 6211da177e4SLinus Torvalds 62220d49473SPatrick Ohly static int ktime2ts(ktime_t kt, struct timespec *ts) 62320d49473SPatrick Ohly { 62420d49473SPatrick Ohly if (kt.tv64) { 62520d49473SPatrick Ohly *ts = ktime_to_timespec(kt); 62620d49473SPatrick Ohly return 1; 62720d49473SPatrick Ohly } else { 62820d49473SPatrick Ohly return 0; 62920d49473SPatrick Ohly } 63020d49473SPatrick Ohly } 63120d49473SPatrick Ohly 63292f37fd2SEric Dumazet /* 63392f37fd2SEric Dumazet * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) 63492f37fd2SEric Dumazet */ 63592f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 63692f37fd2SEric Dumazet struct sk_buff *skb) 63792f37fd2SEric Dumazet { 63820d49473SPatrick Ohly int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 63920d49473SPatrick Ohly struct timespec ts[3]; 64020d49473SPatrick Ohly int empty = 1; 64120d49473SPatrick Ohly struct skb_shared_hwtstamps *shhwtstamps = 64220d49473SPatrick Ohly skb_hwtstamps(skb); 64392f37fd2SEric Dumazet 64420d49473SPatrick Ohly /* Race occurred between timestamp enabling and packet 64520d49473SPatrick Ohly receiving. Fill in the current time for now. */ 64620d49473SPatrick Ohly if (need_software_tstamp && skb->tstamp.tv64 == 0) 64720d49473SPatrick Ohly __net_timestamp(skb); 64820d49473SPatrick Ohly 64920d49473SPatrick Ohly if (need_software_tstamp) { 65092f37fd2SEric Dumazet if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { 65192f37fd2SEric Dumazet struct timeval tv; 65220d49473SPatrick Ohly skb_get_timestamp(skb, &tv); 65320d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, 65420d49473SPatrick Ohly sizeof(tv), &tv); 65592f37fd2SEric Dumazet } else { 656842509b8SHagen Paul Pfeifer skb_get_timestampns(skb, &ts[0]); 65720d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, 658842509b8SHagen Paul Pfeifer sizeof(ts[0]), &ts[0]); 65992f37fd2SEric Dumazet } 66092f37fd2SEric Dumazet } 66192f37fd2SEric Dumazet 66220d49473SPatrick Ohly 66320d49473SPatrick Ohly memset(ts, 0, sizeof(ts)); 66420d49473SPatrick Ohly if (skb->tstamp.tv64 && 66520d49473SPatrick Ohly sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) { 66620d49473SPatrick Ohly skb_get_timestampns(skb, ts + 0); 66720d49473SPatrick Ohly empty = 0; 66820d49473SPatrick Ohly } 66920d49473SPatrick Ohly if (shhwtstamps) { 67020d49473SPatrick Ohly if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) && 67120d49473SPatrick Ohly ktime2ts(shhwtstamps->syststamp, ts + 1)) 67220d49473SPatrick Ohly empty = 0; 67320d49473SPatrick Ohly if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && 67420d49473SPatrick Ohly ktime2ts(shhwtstamps->hwtstamp, ts + 2)) 67520d49473SPatrick Ohly empty = 0; 67620d49473SPatrick Ohly } 67720d49473SPatrick Ohly if (!empty) 67820d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, 67920d49473SPatrick Ohly SCM_TIMESTAMPING, sizeof(ts), &ts); 68020d49473SPatrick Ohly } 6817c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 6827c81fd8bSArnaldo Carvalho de Melo 6836e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, 6846e3e939fSJohannes Berg struct sk_buff *skb) 6856e3e939fSJohannes Berg { 6866e3e939fSJohannes Berg int ack; 6876e3e939fSJohannes Berg 6886e3e939fSJohannes Berg if (!sock_flag(sk, SOCK_WIFI_STATUS)) 6896e3e939fSJohannes Berg return; 6906e3e939fSJohannes Berg if (!skb->wifi_acked_valid) 6916e3e939fSJohannes Berg return; 6926e3e939fSJohannes Berg 6936e3e939fSJohannes Berg ack = skb->wifi_acked; 6946e3e939fSJohannes Berg 6956e3e939fSJohannes Berg put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack); 6966e3e939fSJohannes Berg } 6976e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status); 6986e3e939fSJohannes Berg 69911165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, 70011165f14Sstephen hemminger struct sk_buff *skb) 7013b885787SNeil Horman { 7023b885787SNeil Horman if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount) 7033b885787SNeil Horman put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, 7043b885787SNeil Horman sizeof(__u32), &skb->dropcount); 7053b885787SNeil Horman } 7063b885787SNeil Horman 707767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 7083b885787SNeil Horman struct sk_buff *skb) 7093b885787SNeil Horman { 7103b885787SNeil Horman sock_recv_timestamp(msg, sk, skb); 7113b885787SNeil Horman sock_recv_drops(msg, sk, skb); 7123b885787SNeil Horman } 713767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); 7143b885787SNeil Horman 715a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, 7161da177e4SLinus Torvalds struct msghdr *msg, size_t size, int flags) 7171da177e4SLinus Torvalds { 7181da177e4SLinus Torvalds struct sock_iocb *si = kiocb_to_siocb(iocb); 7191da177e4SLinus Torvalds 720f8451725SHerbert Xu sock_update_classid(sock->sk); 721f8451725SHerbert Xu 7221da177e4SLinus Torvalds si->sock = sock; 7231da177e4SLinus Torvalds si->scm = NULL; 7241da177e4SLinus Torvalds si->msg = msg; 7251da177e4SLinus Torvalds si->size = size; 7261da177e4SLinus Torvalds si->flags = flags; 7271da177e4SLinus Torvalds 7281da177e4SLinus Torvalds return sock->ops->recvmsg(iocb, sock, msg, size, flags); 7291da177e4SLinus Torvalds } 7301da177e4SLinus Torvalds 731a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, 732a2e27255SArnaldo Carvalho de Melo struct msghdr *msg, size_t size, int flags) 733a2e27255SArnaldo Carvalho de Melo { 734a2e27255SArnaldo Carvalho de Melo int err = security_socket_recvmsg(sock, msg, size, flags); 735a2e27255SArnaldo Carvalho de Melo 736a2e27255SArnaldo Carvalho de Melo return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags); 737a2e27255SArnaldo Carvalho de Melo } 738a2e27255SArnaldo Carvalho de Melo 7391da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg, 7401da177e4SLinus Torvalds size_t size, int flags) 7411da177e4SLinus Torvalds { 7421da177e4SLinus Torvalds struct kiocb iocb; 7431da177e4SLinus Torvalds struct sock_iocb siocb; 7441da177e4SLinus Torvalds int ret; 7451da177e4SLinus Torvalds 7461da177e4SLinus Torvalds init_sync_kiocb(&iocb, NULL); 7471da177e4SLinus Torvalds iocb.private = &siocb; 7481da177e4SLinus Torvalds ret = __sock_recvmsg(&iocb, sock, msg, size, flags); 7491da177e4SLinus Torvalds if (-EIOCBQUEUED == ret) 7501da177e4SLinus Torvalds ret = wait_on_sync_kiocb(&iocb); 7511da177e4SLinus Torvalds return ret; 7521da177e4SLinus Torvalds } 753c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg); 7541da177e4SLinus Torvalds 755a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, 756a2e27255SArnaldo Carvalho de Melo size_t size, int flags) 757a2e27255SArnaldo Carvalho de Melo { 758a2e27255SArnaldo Carvalho de Melo struct kiocb iocb; 759a2e27255SArnaldo Carvalho de Melo struct sock_iocb siocb; 760a2e27255SArnaldo Carvalho de Melo int ret; 761a2e27255SArnaldo Carvalho de Melo 762a2e27255SArnaldo Carvalho de Melo init_sync_kiocb(&iocb, NULL); 763a2e27255SArnaldo Carvalho de Melo iocb.private = &siocb; 764a2e27255SArnaldo Carvalho de Melo ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags); 765a2e27255SArnaldo Carvalho de Melo if (-EIOCBQUEUED == ret) 766a2e27255SArnaldo Carvalho de Melo ret = wait_on_sync_kiocb(&iocb); 767a2e27255SArnaldo Carvalho de Melo return ret; 768a2e27255SArnaldo Carvalho de Melo } 769a2e27255SArnaldo Carvalho de Melo 770c1249c0aSMartin Lucina /** 771c1249c0aSMartin Lucina * kernel_recvmsg - Receive a message from a socket (kernel space) 772c1249c0aSMartin Lucina * @sock: The socket to receive the message from 773c1249c0aSMartin Lucina * @msg: Received message 774c1249c0aSMartin Lucina * @vec: Input s/g array for message data 775c1249c0aSMartin Lucina * @num: Size of input s/g array 776c1249c0aSMartin Lucina * @size: Number of bytes to read 777c1249c0aSMartin Lucina * @flags: Message flags (MSG_DONTWAIT, etc...) 778c1249c0aSMartin Lucina * 779c1249c0aSMartin Lucina * On return the msg structure contains the scatter/gather array passed in the 780c1249c0aSMartin Lucina * vec argument. The array is modified so that it consists of the unfilled 781c1249c0aSMartin Lucina * portion of the original array. 782c1249c0aSMartin Lucina * 783c1249c0aSMartin Lucina * The returned value is the total number of bytes received, or an error. 784c1249c0aSMartin Lucina */ 7851da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg, 78689bddce5SStephen Hemminger struct kvec *vec, size_t num, size_t size, int flags) 7871da177e4SLinus Torvalds { 7881da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 7891da177e4SLinus Torvalds int result; 7901da177e4SLinus Torvalds 7911da177e4SLinus Torvalds set_fs(KERNEL_DS); 7921da177e4SLinus Torvalds /* 7931da177e4SLinus Torvalds * the following is safe, since for compiler definitions of kvec and 7941da177e4SLinus Torvalds * iovec are identical, yielding the same in-core layout and alignment 7951da177e4SLinus Torvalds */ 79689bddce5SStephen Hemminger msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num; 7971da177e4SLinus Torvalds result = sock_recvmsg(sock, msg, size, flags); 7981da177e4SLinus Torvalds set_fs(oldfs); 7991da177e4SLinus Torvalds return result; 8001da177e4SLinus Torvalds } 801c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg); 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds static void sock_aio_dtor(struct kiocb *iocb) 8041da177e4SLinus Torvalds { 8051da177e4SLinus Torvalds kfree(iocb->private); 8061da177e4SLinus Torvalds } 8071da177e4SLinus Torvalds 80820380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page, 8091da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more) 8101da177e4SLinus Torvalds { 8111da177e4SLinus Torvalds struct socket *sock; 8121da177e4SLinus Torvalds int flags; 8131da177e4SLinus Torvalds 814b69aee04SEric Dumazet sock = file->private_data; 8151da177e4SLinus Torvalds 81635f9c09fSEric Dumazet flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 81735f9c09fSEric Dumazet /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */ 81835f9c09fSEric Dumazet flags |= more; 8191da177e4SLinus Torvalds 820e6949583SLinus Torvalds return kernel_sendpage(sock, page, offset, size, flags); 8211da177e4SLinus Torvalds } 8221da177e4SLinus Torvalds 8239c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 8249c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 8259c55e01cSJens Axboe unsigned int flags) 8269c55e01cSJens Axboe { 8279c55e01cSJens Axboe struct socket *sock = file->private_data; 8289c55e01cSJens Axboe 829997b37daSRémi Denis-Courmont if (unlikely(!sock->ops->splice_read)) 830997b37daSRémi Denis-Courmont return -EINVAL; 831997b37daSRémi Denis-Courmont 832f8451725SHerbert Xu sock_update_classid(sock->sk); 833f8451725SHerbert Xu 8349c55e01cSJens Axboe return sock->ops->splice_read(sock, ppos, pipe, len, flags); 8359c55e01cSJens Axboe } 8369c55e01cSJens Axboe 837ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, 83889bddce5SStephen Hemminger struct sock_iocb *siocb) 839ce1d4d3eSChristoph Hellwig { 840ce1d4d3eSChristoph Hellwig if (!is_sync_kiocb(iocb)) { 841ce1d4d3eSChristoph Hellwig siocb = kmalloc(sizeof(*siocb), GFP_KERNEL); 842ce1d4d3eSChristoph Hellwig if (!siocb) 843ce1d4d3eSChristoph Hellwig return NULL; 844ce1d4d3eSChristoph Hellwig iocb->ki_dtor = sock_aio_dtor; 845ce1d4d3eSChristoph Hellwig } 846ce1d4d3eSChristoph Hellwig 847ce1d4d3eSChristoph Hellwig siocb->kiocb = iocb; 848ce1d4d3eSChristoph Hellwig iocb->private = siocb; 849ce1d4d3eSChristoph Hellwig return siocb; 850ce1d4d3eSChristoph Hellwig } 851ce1d4d3eSChristoph Hellwig 852ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, 853027445c3SBadari Pulavarty struct file *file, const struct iovec *iov, 85489bddce5SStephen Hemminger unsigned long nr_segs) 855ce1d4d3eSChristoph Hellwig { 856ce1d4d3eSChristoph Hellwig struct socket *sock = file->private_data; 857ce1d4d3eSChristoph Hellwig size_t size = 0; 858ce1d4d3eSChristoph Hellwig int i; 859ce1d4d3eSChristoph Hellwig 860ce1d4d3eSChristoph Hellwig for (i = 0; i < nr_segs; i++) 861ce1d4d3eSChristoph Hellwig size += iov[i].iov_len; 862ce1d4d3eSChristoph Hellwig 863ce1d4d3eSChristoph Hellwig msg->msg_name = NULL; 864ce1d4d3eSChristoph Hellwig msg->msg_namelen = 0; 865ce1d4d3eSChristoph Hellwig msg->msg_control = NULL; 866ce1d4d3eSChristoph Hellwig msg->msg_controllen = 0; 867ce1d4d3eSChristoph Hellwig msg->msg_iov = (struct iovec *)iov; 868ce1d4d3eSChristoph Hellwig msg->msg_iovlen = nr_segs; 869ce1d4d3eSChristoph Hellwig msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 870ce1d4d3eSChristoph Hellwig 871ce1d4d3eSChristoph Hellwig return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags); 872ce1d4d3eSChristoph Hellwig } 873ce1d4d3eSChristoph Hellwig 874027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, 875027445c3SBadari Pulavarty unsigned long nr_segs, loff_t pos) 876ce1d4d3eSChristoph Hellwig { 877ce1d4d3eSChristoph Hellwig struct sock_iocb siocb, *x; 878ce1d4d3eSChristoph Hellwig 879ce1d4d3eSChristoph Hellwig if (pos != 0) 880ce1d4d3eSChristoph Hellwig return -ESPIPE; 881027445c3SBadari Pulavarty 882027445c3SBadari Pulavarty if (iocb->ki_left == 0) /* Match SYS5 behaviour */ 883ce1d4d3eSChristoph Hellwig return 0; 884ce1d4d3eSChristoph Hellwig 885027445c3SBadari Pulavarty 886027445c3SBadari Pulavarty x = alloc_sock_iocb(iocb, &siocb); 887ce1d4d3eSChristoph Hellwig if (!x) 888ce1d4d3eSChristoph Hellwig return -ENOMEM; 889027445c3SBadari Pulavarty return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs); 890ce1d4d3eSChristoph Hellwig } 891ce1d4d3eSChristoph Hellwig 892ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, 893027445c3SBadari Pulavarty struct file *file, const struct iovec *iov, 89489bddce5SStephen Hemminger unsigned long nr_segs) 895ce1d4d3eSChristoph Hellwig { 896ce1d4d3eSChristoph Hellwig struct socket *sock = file->private_data; 897ce1d4d3eSChristoph Hellwig size_t size = 0; 898ce1d4d3eSChristoph Hellwig int i; 899ce1d4d3eSChristoph Hellwig 900ce1d4d3eSChristoph Hellwig for (i = 0; i < nr_segs; i++) 901ce1d4d3eSChristoph Hellwig size += iov[i].iov_len; 902ce1d4d3eSChristoph Hellwig 903ce1d4d3eSChristoph Hellwig msg->msg_name = NULL; 904ce1d4d3eSChristoph Hellwig msg->msg_namelen = 0; 905ce1d4d3eSChristoph Hellwig msg->msg_control = NULL; 906ce1d4d3eSChristoph Hellwig msg->msg_controllen = 0; 907ce1d4d3eSChristoph Hellwig msg->msg_iov = (struct iovec *)iov; 908ce1d4d3eSChristoph Hellwig msg->msg_iovlen = nr_segs; 909ce1d4d3eSChristoph Hellwig msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 910ce1d4d3eSChristoph Hellwig if (sock->type == SOCK_SEQPACKET) 911ce1d4d3eSChristoph Hellwig msg->msg_flags |= MSG_EOR; 912ce1d4d3eSChristoph Hellwig 913ce1d4d3eSChristoph Hellwig return __sock_sendmsg(iocb, sock, msg, size); 914ce1d4d3eSChristoph Hellwig } 915ce1d4d3eSChristoph Hellwig 916027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, 917027445c3SBadari Pulavarty unsigned long nr_segs, loff_t pos) 9181da177e4SLinus Torvalds { 919ce1d4d3eSChristoph Hellwig struct sock_iocb siocb, *x; 9201da177e4SLinus Torvalds 921ce1d4d3eSChristoph Hellwig if (pos != 0) 922ce1d4d3eSChristoph Hellwig return -ESPIPE; 923027445c3SBadari Pulavarty 924027445c3SBadari Pulavarty x = alloc_sock_iocb(iocb, &siocb); 925ce1d4d3eSChristoph Hellwig if (!x) 926ce1d4d3eSChristoph Hellwig return -ENOMEM; 927ce1d4d3eSChristoph Hellwig 928027445c3SBadari Pulavarty return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs); 9291da177e4SLinus Torvalds } 9301da177e4SLinus Torvalds 9311da177e4SLinus Torvalds /* 9321da177e4SLinus Torvalds * Atomic setting of ioctl hooks to avoid race 9331da177e4SLinus Torvalds * with module unload. 9341da177e4SLinus Torvalds */ 9351da177e4SLinus Torvalds 9364a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex); 937c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg); 9381da177e4SLinus Torvalds 939881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *)) 9401da177e4SLinus Torvalds { 9414a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 9421da177e4SLinus Torvalds br_ioctl_hook = hook; 9434a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 9441da177e4SLinus Torvalds } 9451da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set); 9461da177e4SLinus Torvalds 9474a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex); 948881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg); 9491da177e4SLinus Torvalds 950881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *)) 9511da177e4SLinus Torvalds { 9524a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 9531da177e4SLinus Torvalds vlan_ioctl_hook = hook; 9544a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 9551da177e4SLinus Torvalds } 9561da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set); 9571da177e4SLinus Torvalds 9584a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex); 9591da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *); 9601da177e4SLinus Torvalds 9611da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) 9621da177e4SLinus Torvalds { 9634a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 9641da177e4SLinus Torvalds dlci_ioctl_hook = hook; 9654a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 9661da177e4SLinus Torvalds } 9671da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set); 9681da177e4SLinus Torvalds 9696b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock, 9706b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 9716b96018bSArnd Bergmann { 9726b96018bSArnd Bergmann int err; 9736b96018bSArnd Bergmann void __user *argp = (void __user *)arg; 9746b96018bSArnd Bergmann 9756b96018bSArnd Bergmann err = sock->ops->ioctl(sock, cmd, arg); 9766b96018bSArnd Bergmann 9776b96018bSArnd Bergmann /* 9786b96018bSArnd Bergmann * If this ioctl is unknown try to hand it down 9796b96018bSArnd Bergmann * to the NIC driver. 9806b96018bSArnd Bergmann */ 9816b96018bSArnd Bergmann if (err == -ENOIOCTLCMD) 9826b96018bSArnd Bergmann err = dev_ioctl(net, cmd, argp); 9836b96018bSArnd Bergmann 9846b96018bSArnd Bergmann return err; 9856b96018bSArnd Bergmann } 9866b96018bSArnd Bergmann 9871da177e4SLinus Torvalds /* 9881da177e4SLinus Torvalds * With an ioctl, arg may well be a user mode pointer, but we don't know 9891da177e4SLinus Torvalds * what to do with it - that's up to the protocol still. 9901da177e4SLinus Torvalds */ 9911da177e4SLinus Torvalds 9921da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) 9931da177e4SLinus Torvalds { 9941da177e4SLinus Torvalds struct socket *sock; 995881d966bSEric W. Biederman struct sock *sk; 9961da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 9971da177e4SLinus Torvalds int pid, err; 998881d966bSEric W. Biederman struct net *net; 9991da177e4SLinus Torvalds 1000b69aee04SEric Dumazet sock = file->private_data; 1001881d966bSEric W. Biederman sk = sock->sk; 10023b1e0a65SYOSHIFUJI Hideaki net = sock_net(sk); 10031da177e4SLinus Torvalds if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { 1004881d966bSEric W. Biederman err = dev_ioctl(net, cmd, argp); 10051da177e4SLinus Torvalds } else 10063d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE 10071da177e4SLinus Torvalds if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { 1008881d966bSEric W. Biederman err = dev_ioctl(net, cmd, argp); 10091da177e4SLinus Torvalds } else 10103d23e349SJohannes Berg #endif 10111da177e4SLinus Torvalds switch (cmd) { 10121da177e4SLinus Torvalds case FIOSETOWN: 10131da177e4SLinus Torvalds case SIOCSPGRP: 10141da177e4SLinus Torvalds err = -EFAULT; 10151da177e4SLinus Torvalds if (get_user(pid, (int __user *)argp)) 10161da177e4SLinus Torvalds break; 10171da177e4SLinus Torvalds err = f_setown(sock->file, pid, 1); 10181da177e4SLinus Torvalds break; 10191da177e4SLinus Torvalds case FIOGETOWN: 10201da177e4SLinus Torvalds case SIOCGPGRP: 1021609d7fa9SEric W. Biederman err = put_user(f_getown(sock->file), 102289bddce5SStephen Hemminger (int __user *)argp); 10231da177e4SLinus Torvalds break; 10241da177e4SLinus Torvalds case SIOCGIFBR: 10251da177e4SLinus Torvalds case SIOCSIFBR: 10261da177e4SLinus Torvalds case SIOCBRADDBR: 10271da177e4SLinus Torvalds case SIOCBRDELBR: 10281da177e4SLinus Torvalds err = -ENOPKG; 10291da177e4SLinus Torvalds if (!br_ioctl_hook) 10301da177e4SLinus Torvalds request_module("bridge"); 10311da177e4SLinus Torvalds 10324a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 10331da177e4SLinus Torvalds if (br_ioctl_hook) 1034881d966bSEric W. Biederman err = br_ioctl_hook(net, cmd, argp); 10354a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 10361da177e4SLinus Torvalds break; 10371da177e4SLinus Torvalds case SIOCGIFVLAN: 10381da177e4SLinus Torvalds case SIOCSIFVLAN: 10391da177e4SLinus Torvalds err = -ENOPKG; 10401da177e4SLinus Torvalds if (!vlan_ioctl_hook) 10411da177e4SLinus Torvalds request_module("8021q"); 10421da177e4SLinus Torvalds 10434a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 10441da177e4SLinus Torvalds if (vlan_ioctl_hook) 1045881d966bSEric W. Biederman err = vlan_ioctl_hook(net, argp); 10464a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 10471da177e4SLinus Torvalds break; 10481da177e4SLinus Torvalds case SIOCADDDLCI: 10491da177e4SLinus Torvalds case SIOCDELDLCI: 10501da177e4SLinus Torvalds err = -ENOPKG; 10511da177e4SLinus Torvalds if (!dlci_ioctl_hook) 10521da177e4SLinus Torvalds request_module("dlci"); 10531da177e4SLinus Torvalds 10544a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 10557512cbf6SPavel Emelyanov if (dlci_ioctl_hook) 10561da177e4SLinus Torvalds err = dlci_ioctl_hook(cmd, argp); 10574a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 10581da177e4SLinus Torvalds break; 10591da177e4SLinus Torvalds default: 10606b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, arg); 10611da177e4SLinus Torvalds break; 10621da177e4SLinus Torvalds } 10631da177e4SLinus Torvalds return err; 10641da177e4SLinus Torvalds } 10651da177e4SLinus Torvalds 10661da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res) 10671da177e4SLinus Torvalds { 10681da177e4SLinus Torvalds int err; 10691da177e4SLinus Torvalds struct socket *sock = NULL; 10701da177e4SLinus Torvalds 10711da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, 1); 10721da177e4SLinus Torvalds if (err) 10731da177e4SLinus Torvalds goto out; 10741da177e4SLinus Torvalds 10751da177e4SLinus Torvalds sock = sock_alloc(); 10761da177e4SLinus Torvalds if (!sock) { 10771da177e4SLinus Torvalds err = -ENOMEM; 10781da177e4SLinus Torvalds goto out; 10791da177e4SLinus Torvalds } 10801da177e4SLinus Torvalds 10811da177e4SLinus Torvalds sock->type = type; 10827420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, 1); 10837420ed23SVenkat Yekkirala if (err) 10847420ed23SVenkat Yekkirala goto out_release; 10857420ed23SVenkat Yekkirala 10861da177e4SLinus Torvalds out: 10871da177e4SLinus Torvalds *res = sock; 10881da177e4SLinus Torvalds return err; 10897420ed23SVenkat Yekkirala out_release: 10907420ed23SVenkat Yekkirala sock_release(sock); 10917420ed23SVenkat Yekkirala sock = NULL; 10927420ed23SVenkat Yekkirala goto out; 10931da177e4SLinus Torvalds } 1094c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite); 10951da177e4SLinus Torvalds 10961da177e4SLinus Torvalds /* No kernel lock held - perfect */ 10971da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait) 10981da177e4SLinus Torvalds { 10991da177e4SLinus Torvalds struct socket *sock; 11001da177e4SLinus Torvalds 11011da177e4SLinus Torvalds /* 11021da177e4SLinus Torvalds * We can't return errors to poll, so it's either yes or no. 11031da177e4SLinus Torvalds */ 1104b69aee04SEric Dumazet sock = file->private_data; 11051da177e4SLinus Torvalds return sock->ops->poll(file, sock, wait); 11061da177e4SLinus Torvalds } 11071da177e4SLinus Torvalds 11081da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma) 11091da177e4SLinus Torvalds { 1110b69aee04SEric Dumazet struct socket *sock = file->private_data; 11111da177e4SLinus Torvalds 11121da177e4SLinus Torvalds return sock->ops->mmap(file, sock, vma); 11131da177e4SLinus Torvalds } 11141da177e4SLinus Torvalds 111520380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp) 11161da177e4SLinus Torvalds { 11171da177e4SLinus Torvalds /* 11181da177e4SLinus Torvalds * It was possible the inode is NULL we were 11191da177e4SLinus Torvalds * closing an unfinished socket. 11201da177e4SLinus Torvalds */ 11211da177e4SLinus Torvalds 112289bddce5SStephen Hemminger if (!inode) { 11231da177e4SLinus Torvalds printk(KERN_DEBUG "sock_close: NULL inode\n"); 11241da177e4SLinus Torvalds return 0; 11251da177e4SLinus Torvalds } 11261da177e4SLinus Torvalds sock_release(SOCKET_I(inode)); 11271da177e4SLinus Torvalds return 0; 11281da177e4SLinus Torvalds } 11291da177e4SLinus Torvalds 11301da177e4SLinus Torvalds /* 11311da177e4SLinus Torvalds * Update the socket async list 11321da177e4SLinus Torvalds * 11331da177e4SLinus Torvalds * Fasync_list locking strategy. 11341da177e4SLinus Torvalds * 11351da177e4SLinus Torvalds * 1. fasync_list is modified only under process context socket lock 11361da177e4SLinus Torvalds * i.e. under semaphore. 11371da177e4SLinus Torvalds * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1138989a2979SEric Dumazet * or under socket lock 11391da177e4SLinus Torvalds */ 11401da177e4SLinus Torvalds 11411da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on) 11421da177e4SLinus Torvalds { 1143989a2979SEric Dumazet struct socket *sock = filp->private_data; 1144989a2979SEric Dumazet struct sock *sk = sock->sk; 1145eaefd110SEric Dumazet struct socket_wq *wq; 11461da177e4SLinus Torvalds 1147989a2979SEric Dumazet if (sk == NULL) 11481da177e4SLinus Torvalds return -EINVAL; 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds lock_sock(sk); 1151eaefd110SEric Dumazet wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk)); 1152eaefd110SEric Dumazet fasync_helper(fd, filp, on, &wq->fasync_list); 11531da177e4SLinus Torvalds 1154eaefd110SEric Dumazet if (!wq->fasync_list) 1155bcdce719SEric Dumazet sock_reset_flag(sk, SOCK_FASYNC); 1156989a2979SEric Dumazet else 1157989a2979SEric Dumazet sock_set_flag(sk, SOCK_FASYNC); 11581da177e4SLinus Torvalds 1159989a2979SEric Dumazet release_sock(sk); 11601da177e4SLinus Torvalds return 0; 11611da177e4SLinus Torvalds } 11621da177e4SLinus Torvalds 116343815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */ 11641da177e4SLinus Torvalds 11651da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band) 11661da177e4SLinus Torvalds { 116743815482SEric Dumazet struct socket_wq *wq; 116843815482SEric Dumazet 116943815482SEric Dumazet if (!sock) 11701da177e4SLinus Torvalds return -1; 117143815482SEric Dumazet rcu_read_lock(); 117243815482SEric Dumazet wq = rcu_dereference(sock->wq); 117343815482SEric Dumazet if (!wq || !wq->fasync_list) { 117443815482SEric Dumazet rcu_read_unlock(); 117543815482SEric Dumazet return -1; 117643815482SEric Dumazet } 117789bddce5SStephen Hemminger switch (how) { 11788d8ad9d7SPavel Emelyanov case SOCK_WAKE_WAITD: 11791da177e4SLinus Torvalds if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) 11801da177e4SLinus Torvalds break; 11811da177e4SLinus Torvalds goto call_kill; 11828d8ad9d7SPavel Emelyanov case SOCK_WAKE_SPACE: 11831da177e4SLinus Torvalds if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags)) 11841da177e4SLinus Torvalds break; 11851da177e4SLinus Torvalds /* fall through */ 11868d8ad9d7SPavel Emelyanov case SOCK_WAKE_IO: 11871da177e4SLinus Torvalds call_kill: 118843815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGIO, band); 11891da177e4SLinus Torvalds break; 11908d8ad9d7SPavel Emelyanov case SOCK_WAKE_URG: 119143815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGURG, band); 11921da177e4SLinus Torvalds } 119343815482SEric Dumazet rcu_read_unlock(); 11941da177e4SLinus Torvalds return 0; 11951da177e4SLinus Torvalds } 1196c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async); 11971da177e4SLinus Torvalds 1198721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol, 119989bddce5SStephen Hemminger struct socket **res, int kern) 12001da177e4SLinus Torvalds { 12011da177e4SLinus Torvalds int err; 12021da177e4SLinus Torvalds struct socket *sock; 120355737fdaSStephen Hemminger const struct net_proto_family *pf; 12041da177e4SLinus Torvalds 12051da177e4SLinus Torvalds /* 12061da177e4SLinus Torvalds * Check protocol is in range 12071da177e4SLinus Torvalds */ 12081da177e4SLinus Torvalds if (family < 0 || family >= NPROTO) 12091da177e4SLinus Torvalds return -EAFNOSUPPORT; 12101da177e4SLinus Torvalds if (type < 0 || type >= SOCK_MAX) 12111da177e4SLinus Torvalds return -EINVAL; 12121da177e4SLinus Torvalds 12131da177e4SLinus Torvalds /* Compatibility. 12141da177e4SLinus Torvalds 12151da177e4SLinus Torvalds This uglymoron is moved from INET layer to here to avoid 12161da177e4SLinus Torvalds deadlock in module load. 12171da177e4SLinus Torvalds */ 12181da177e4SLinus Torvalds if (family == PF_INET && type == SOCK_PACKET) { 12191da177e4SLinus Torvalds static int warned; 12201da177e4SLinus Torvalds if (!warned) { 12211da177e4SLinus Torvalds warned = 1; 122289bddce5SStephen Hemminger printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", 122389bddce5SStephen Hemminger current->comm); 12241da177e4SLinus Torvalds } 12251da177e4SLinus Torvalds family = PF_PACKET; 12261da177e4SLinus Torvalds } 12271da177e4SLinus Torvalds 12281da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, kern); 12291da177e4SLinus Torvalds if (err) 12301da177e4SLinus Torvalds return err; 12311da177e4SLinus Torvalds 123255737fdaSStephen Hemminger /* 123355737fdaSStephen Hemminger * Allocate the socket and allow the family to set things up. if 123455737fdaSStephen Hemminger * the protocol is 0, the family is instructed to select an appropriate 123555737fdaSStephen Hemminger * default. 123655737fdaSStephen Hemminger */ 123755737fdaSStephen Hemminger sock = sock_alloc(); 123855737fdaSStephen Hemminger if (!sock) { 1239e87cc472SJoe Perches net_warn_ratelimited("socket: no more sockets\n"); 124055737fdaSStephen Hemminger return -ENFILE; /* Not exactly a match, but its the 124155737fdaSStephen Hemminger closest posix thing */ 124255737fdaSStephen Hemminger } 124355737fdaSStephen Hemminger 124455737fdaSStephen Hemminger sock->type = type; 124555737fdaSStephen Hemminger 124695a5afcaSJohannes Berg #ifdef CONFIG_MODULES 12471da177e4SLinus Torvalds /* Attempt to load a protocol module if the find failed. 12481da177e4SLinus Torvalds * 12491da177e4SLinus Torvalds * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user 12501da177e4SLinus Torvalds * requested real, full-featured networking support upon configuration. 12511da177e4SLinus Torvalds * Otherwise module support will break! 12521da177e4SLinus Torvalds */ 1253190683a9SEric Dumazet if (rcu_access_pointer(net_families[family]) == NULL) 12541da177e4SLinus Torvalds request_module("net-pf-%d", family); 12551da177e4SLinus Torvalds #endif 12561da177e4SLinus Torvalds 125755737fdaSStephen Hemminger rcu_read_lock(); 125855737fdaSStephen Hemminger pf = rcu_dereference(net_families[family]); 12591da177e4SLinus Torvalds err = -EAFNOSUPPORT; 126055737fdaSStephen Hemminger if (!pf) 126155737fdaSStephen Hemminger goto out_release; 12621da177e4SLinus Torvalds 12631da177e4SLinus Torvalds /* 12641da177e4SLinus Torvalds * We will call the ->create function, that possibly is in a loadable 12651da177e4SLinus Torvalds * module, so we have to bump that loadable module refcnt first. 12661da177e4SLinus Torvalds */ 126755737fdaSStephen Hemminger if (!try_module_get(pf->owner)) 12681da177e4SLinus Torvalds goto out_release; 12691da177e4SLinus Torvalds 127055737fdaSStephen Hemminger /* Now protected by module ref count */ 127155737fdaSStephen Hemminger rcu_read_unlock(); 127255737fdaSStephen Hemminger 12733f378b68SEric Paris err = pf->create(net, sock, protocol, kern); 127455737fdaSStephen Hemminger if (err < 0) 12751da177e4SLinus Torvalds goto out_module_put; 1276a79af59eSFrank Filz 12771da177e4SLinus Torvalds /* 12781da177e4SLinus Torvalds * Now to bump the refcnt of the [loadable] module that owns this 12791da177e4SLinus Torvalds * socket at sock_release time we decrement its refcnt. 12801da177e4SLinus Torvalds */ 128155737fdaSStephen Hemminger if (!try_module_get(sock->ops->owner)) 128255737fdaSStephen Hemminger goto out_module_busy; 128355737fdaSStephen Hemminger 12841da177e4SLinus Torvalds /* 12851da177e4SLinus Torvalds * Now that we're done with the ->create function, the [loadable] 12861da177e4SLinus Torvalds * module can have its refcnt decremented 12871da177e4SLinus Torvalds */ 128855737fdaSStephen Hemminger module_put(pf->owner); 12897420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, kern); 12907420ed23SVenkat Yekkirala if (err) 12913b185525SHerbert Xu goto out_sock_release; 129255737fdaSStephen Hemminger *res = sock; 12931da177e4SLinus Torvalds 129455737fdaSStephen Hemminger return 0; 129555737fdaSStephen Hemminger 129655737fdaSStephen Hemminger out_module_busy: 129755737fdaSStephen Hemminger err = -EAFNOSUPPORT; 12981da177e4SLinus Torvalds out_module_put: 129955737fdaSStephen Hemminger sock->ops = NULL; 130055737fdaSStephen Hemminger module_put(pf->owner); 130155737fdaSStephen Hemminger out_sock_release: 13021da177e4SLinus Torvalds sock_release(sock); 130355737fdaSStephen Hemminger return err; 130455737fdaSStephen Hemminger 130555737fdaSStephen Hemminger out_release: 130655737fdaSStephen Hemminger rcu_read_unlock(); 130755737fdaSStephen Hemminger goto out_sock_release; 13081da177e4SLinus Torvalds } 1309721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create); 13101da177e4SLinus Torvalds 13111da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res) 13121da177e4SLinus Torvalds { 13131b8d7ae4SEric W. Biederman return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); 13141da177e4SLinus Torvalds } 1315c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create); 13161da177e4SLinus Torvalds 13171da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res) 13181da177e4SLinus Torvalds { 13191b8d7ae4SEric W. Biederman return __sock_create(&init_net, family, type, protocol, res, 1); 13201da177e4SLinus Torvalds } 1321c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern); 13221da177e4SLinus Torvalds 13233e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) 13241da177e4SLinus Torvalds { 13251da177e4SLinus Torvalds int retval; 13261da177e4SLinus Torvalds struct socket *sock; 1327a677a039SUlrich Drepper int flags; 1328a677a039SUlrich Drepper 1329e38b36f3SUlrich Drepper /* Check the SOCK_* constants for consistency. */ 1330e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); 1331e38b36f3SUlrich Drepper BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); 1332e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); 1333e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); 1334e38b36f3SUlrich Drepper 1335a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 133677d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1337a677a039SUlrich Drepper return -EINVAL; 1338a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13391da177e4SLinus Torvalds 1340aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1341aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1342aaca0bdcSUlrich Drepper 13431da177e4SLinus Torvalds retval = sock_create(family, type, protocol, &sock); 13441da177e4SLinus Torvalds if (retval < 0) 13451da177e4SLinus Torvalds goto out; 13461da177e4SLinus Torvalds 134777d27200SUlrich Drepper retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); 13481da177e4SLinus Torvalds if (retval < 0) 13491da177e4SLinus Torvalds goto out_release; 13501da177e4SLinus Torvalds 13511da177e4SLinus Torvalds out: 13521da177e4SLinus Torvalds /* It may be already another descriptor 8) Not kernel problem. */ 13531da177e4SLinus Torvalds return retval; 13541da177e4SLinus Torvalds 13551da177e4SLinus Torvalds out_release: 13561da177e4SLinus Torvalds sock_release(sock); 13571da177e4SLinus Torvalds return retval; 13581da177e4SLinus Torvalds } 13591da177e4SLinus Torvalds 13601da177e4SLinus Torvalds /* 13611da177e4SLinus Torvalds * Create a pair of connected sockets. 13621da177e4SLinus Torvalds */ 13631da177e4SLinus Torvalds 13643e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, 13653e0fa65fSHeiko Carstens int __user *, usockvec) 13661da177e4SLinus Torvalds { 13671da177e4SLinus Torvalds struct socket *sock1, *sock2; 13681da177e4SLinus Torvalds int fd1, fd2, err; 1369db349509SAl Viro struct file *newfile1, *newfile2; 1370a677a039SUlrich Drepper int flags; 1371a677a039SUlrich Drepper 1372a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 137377d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1374a677a039SUlrich Drepper return -EINVAL; 1375a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13761da177e4SLinus Torvalds 1377aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1378aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1379aaca0bdcSUlrich Drepper 13801da177e4SLinus Torvalds /* 13811da177e4SLinus Torvalds * Obtain the first socket and check if the underlying protocol 13821da177e4SLinus Torvalds * supports the socketpair call. 13831da177e4SLinus Torvalds */ 13841da177e4SLinus Torvalds 13851da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock1); 13861da177e4SLinus Torvalds if (err < 0) 13871da177e4SLinus Torvalds goto out; 13881da177e4SLinus Torvalds 13891da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock2); 13901da177e4SLinus Torvalds if (err < 0) 13911da177e4SLinus Torvalds goto out_release_1; 13921da177e4SLinus Torvalds 13931da177e4SLinus Torvalds err = sock1->ops->socketpair(sock1, sock2); 13941da177e4SLinus Torvalds if (err < 0) 13951da177e4SLinus Torvalds goto out_release_both; 13961da177e4SLinus Torvalds 13977cbe66b6SAl Viro fd1 = sock_alloc_file(sock1, &newfile1, flags); 1398bf3c23d1SDavid S. Miller if (unlikely(fd1 < 0)) { 1399bf3c23d1SDavid S. Miller err = fd1; 14001da177e4SLinus Torvalds goto out_release_both; 1401bf3c23d1SDavid S. Miller } 14021da177e4SLinus Torvalds 14037cbe66b6SAl Viro fd2 = sock_alloc_file(sock2, &newfile2, flags); 1404198de4d7SAl Viro if (unlikely(fd2 < 0)) { 1405198de4d7SAl Viro err = fd2; 1406198de4d7SAl Viro fput(newfile1); 1407198de4d7SAl Viro put_unused_fd(fd1); 1408198de4d7SAl Viro sock_release(sock2); 1409198de4d7SAl Viro goto out; 1410db349509SAl Viro } 1411db349509SAl Viro 1412157cf649SAl Viro audit_fd_pair(fd1, fd2); 1413db349509SAl Viro fd_install(fd1, newfile1); 1414db349509SAl Viro fd_install(fd2, newfile2); 14151da177e4SLinus Torvalds /* fd1 and fd2 may be already another descriptors. 14161da177e4SLinus Torvalds * Not kernel problem. 14171da177e4SLinus Torvalds */ 14181da177e4SLinus Torvalds 14191da177e4SLinus Torvalds err = put_user(fd1, &usockvec[0]); 14201da177e4SLinus Torvalds if (!err) 14211da177e4SLinus Torvalds err = put_user(fd2, &usockvec[1]); 14221da177e4SLinus Torvalds if (!err) 14231da177e4SLinus Torvalds return 0; 14241da177e4SLinus Torvalds 14251da177e4SLinus Torvalds sys_close(fd2); 14261da177e4SLinus Torvalds sys_close(fd1); 14271da177e4SLinus Torvalds return err; 14281da177e4SLinus Torvalds 14291da177e4SLinus Torvalds out_release_both: 14301da177e4SLinus Torvalds sock_release(sock2); 14311da177e4SLinus Torvalds out_release_1: 14321da177e4SLinus Torvalds sock_release(sock1); 14331da177e4SLinus Torvalds out: 14341da177e4SLinus Torvalds return err; 14351da177e4SLinus Torvalds } 14361da177e4SLinus Torvalds 14371da177e4SLinus Torvalds /* 14381da177e4SLinus Torvalds * Bind a name to a socket. Nothing much to do here since it's 14391da177e4SLinus Torvalds * the protocol's responsibility to handle the local address. 14401da177e4SLinus Torvalds * 14411da177e4SLinus Torvalds * We move the socket address to kernel space before we call 14421da177e4SLinus Torvalds * the protocol layer (having also checked the address is ok). 14431da177e4SLinus Torvalds */ 14441da177e4SLinus Torvalds 144520f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) 14461da177e4SLinus Torvalds { 14471da177e4SLinus Torvalds struct socket *sock; 1448230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 14496cb153caSBenjamin LaHaise int err, fput_needed; 14501da177e4SLinus Torvalds 145189bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 145289bddce5SStephen Hemminger if (sock) { 145343db362dSMaciej Żenczykowski err = move_addr_to_kernel(umyaddr, addrlen, &address); 145489bddce5SStephen Hemminger if (err >= 0) { 145589bddce5SStephen Hemminger err = security_socket_bind(sock, 1456230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 145789bddce5SStephen Hemminger addrlen); 14586cb153caSBenjamin LaHaise if (!err) 14596cb153caSBenjamin LaHaise err = sock->ops->bind(sock, 146089bddce5SStephen Hemminger (struct sockaddr *) 1461230b1839SYOSHIFUJI Hideaki &address, addrlen); 14621da177e4SLinus Torvalds } 14636cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 14641da177e4SLinus Torvalds } 14651da177e4SLinus Torvalds return err; 14661da177e4SLinus Torvalds } 14671da177e4SLinus Torvalds 14681da177e4SLinus Torvalds /* 14691da177e4SLinus Torvalds * Perform a listen. Basically, we allow the protocol to do anything 14701da177e4SLinus Torvalds * necessary for a listen, and if that works, we mark the socket as 14711da177e4SLinus Torvalds * ready for listening. 14721da177e4SLinus Torvalds */ 14731da177e4SLinus Torvalds 14743e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog) 14751da177e4SLinus Torvalds { 14761da177e4SLinus Torvalds struct socket *sock; 14776cb153caSBenjamin LaHaise int err, fput_needed; 1478b8e1f9b5SPavel Emelyanov int somaxconn; 14791da177e4SLinus Torvalds 148089bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 148189bddce5SStephen Hemminger if (sock) { 14828efa6e93SPavel Emelyanov somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 148395c96174SEric Dumazet if ((unsigned int)backlog > somaxconn) 1484b8e1f9b5SPavel Emelyanov backlog = somaxconn; 14851da177e4SLinus Torvalds 14861da177e4SLinus Torvalds err = security_socket_listen(sock, backlog); 14876cb153caSBenjamin LaHaise if (!err) 14881da177e4SLinus Torvalds err = sock->ops->listen(sock, backlog); 14896cb153caSBenjamin LaHaise 14906cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 14911da177e4SLinus Torvalds } 14921da177e4SLinus Torvalds return err; 14931da177e4SLinus Torvalds } 14941da177e4SLinus Torvalds 14951da177e4SLinus Torvalds /* 14961da177e4SLinus Torvalds * For accept, we attempt to create a new socket, set up the link 14971da177e4SLinus Torvalds * with the client, wake up the client, then return the new 14981da177e4SLinus Torvalds * connected fd. We collect the address of the connector in kernel 14991da177e4SLinus Torvalds * space and move it to user at the very end. This is unclean because 15001da177e4SLinus Torvalds * we open the socket then return an error. 15011da177e4SLinus Torvalds * 15021da177e4SLinus Torvalds * 1003.1g adds the ability to recvmsg() to query connection pending 15031da177e4SLinus Torvalds * status to recvmsg. We need to add that support in a way thats 15041da177e4SLinus Torvalds * clean when we restucture accept also. 15051da177e4SLinus Torvalds */ 15061da177e4SLinus Torvalds 150720f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, 150820f37034SHeiko Carstens int __user *, upeer_addrlen, int, flags) 15091da177e4SLinus Torvalds { 15101da177e4SLinus Torvalds struct socket *sock, *newsock; 151139d8c1b6SDavid S. Miller struct file *newfile; 15126cb153caSBenjamin LaHaise int err, len, newfd, fput_needed; 1513230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 15141da177e4SLinus Torvalds 151577d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1516aaca0bdcSUlrich Drepper return -EINVAL; 1517aaca0bdcSUlrich Drepper 1518aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1519aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1520aaca0bdcSUlrich Drepper 15216cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 15221da177e4SLinus Torvalds if (!sock) 15231da177e4SLinus Torvalds goto out; 15241da177e4SLinus Torvalds 15251da177e4SLinus Torvalds err = -ENFILE; 1526c6d409cfSEric Dumazet newsock = sock_alloc(); 1527c6d409cfSEric Dumazet if (!newsock) 15281da177e4SLinus Torvalds goto out_put; 15291da177e4SLinus Torvalds 15301da177e4SLinus Torvalds newsock->type = sock->type; 15311da177e4SLinus Torvalds newsock->ops = sock->ops; 15321da177e4SLinus Torvalds 15331da177e4SLinus Torvalds /* 15341da177e4SLinus Torvalds * We don't need try_module_get here, as the listening socket (sock) 15351da177e4SLinus Torvalds * has the protocol module (sock->ops->owner) held. 15361da177e4SLinus Torvalds */ 15371da177e4SLinus Torvalds __module_get(newsock->ops->owner); 15381da177e4SLinus Torvalds 15397cbe66b6SAl Viro newfd = sock_alloc_file(newsock, &newfile, flags); 154039d8c1b6SDavid S. Miller if (unlikely(newfd < 0)) { 154139d8c1b6SDavid S. Miller err = newfd; 15429a1875e6SDavid S. Miller sock_release(newsock); 15439a1875e6SDavid S. Miller goto out_put; 154439d8c1b6SDavid S. Miller } 154539d8c1b6SDavid S. Miller 1546a79af59eSFrank Filz err = security_socket_accept(sock, newsock); 1547a79af59eSFrank Filz if (err) 154839d8c1b6SDavid S. Miller goto out_fd; 1549a79af59eSFrank Filz 15501da177e4SLinus Torvalds err = sock->ops->accept(sock, newsock, sock->file->f_flags); 15511da177e4SLinus Torvalds if (err < 0) 155239d8c1b6SDavid S. Miller goto out_fd; 15531da177e4SLinus Torvalds 15541da177e4SLinus Torvalds if (upeer_sockaddr) { 1555230b1839SYOSHIFUJI Hideaki if (newsock->ops->getname(newsock, (struct sockaddr *)&address, 155689bddce5SStephen Hemminger &len, 2) < 0) { 15571da177e4SLinus Torvalds err = -ECONNABORTED; 155839d8c1b6SDavid S. Miller goto out_fd; 15591da177e4SLinus Torvalds } 156043db362dSMaciej Żenczykowski err = move_addr_to_user(&address, 1561230b1839SYOSHIFUJI Hideaki len, upeer_sockaddr, upeer_addrlen); 15621da177e4SLinus Torvalds if (err < 0) 156339d8c1b6SDavid S. Miller goto out_fd; 15641da177e4SLinus Torvalds } 15651da177e4SLinus Torvalds 15661da177e4SLinus Torvalds /* File flags are not inherited via accept() unlike another OSes. */ 15671da177e4SLinus Torvalds 156839d8c1b6SDavid S. Miller fd_install(newfd, newfile); 156939d8c1b6SDavid S. Miller err = newfd; 15701da177e4SLinus Torvalds 15711da177e4SLinus Torvalds out_put: 15726cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 15731da177e4SLinus Torvalds out: 15741da177e4SLinus Torvalds return err; 157539d8c1b6SDavid S. Miller out_fd: 15769606a216SDavid S. Miller fput(newfile); 157739d8c1b6SDavid S. Miller put_unused_fd(newfd); 15781da177e4SLinus Torvalds goto out_put; 15791da177e4SLinus Torvalds } 15801da177e4SLinus Torvalds 158120f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, 158220f37034SHeiko Carstens int __user *, upeer_addrlen) 1583aaca0bdcSUlrich Drepper { 1584de11defeSUlrich Drepper return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); 1585aaca0bdcSUlrich Drepper } 1586aaca0bdcSUlrich Drepper 15871da177e4SLinus Torvalds /* 15881da177e4SLinus Torvalds * Attempt to connect to a socket with the server address. The address 15891da177e4SLinus Torvalds * is in user space so we verify it is OK and move it to kernel space. 15901da177e4SLinus Torvalds * 15911da177e4SLinus Torvalds * For 1003.1g we need to add clean support for a bind to AF_UNSPEC to 15921da177e4SLinus Torvalds * break bindings 15931da177e4SLinus Torvalds * 15941da177e4SLinus Torvalds * NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and 15951da177e4SLinus Torvalds * other SEQPACKET protocols that take time to connect() as it doesn't 15961da177e4SLinus Torvalds * include the -EINPROGRESS status for such sockets. 15971da177e4SLinus Torvalds */ 15981da177e4SLinus Torvalds 159920f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, 160020f37034SHeiko Carstens int, addrlen) 16011da177e4SLinus Torvalds { 16021da177e4SLinus Torvalds struct socket *sock; 1603230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16046cb153caSBenjamin LaHaise int err, fput_needed; 16051da177e4SLinus Torvalds 16066cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16071da177e4SLinus Torvalds if (!sock) 16081da177e4SLinus Torvalds goto out; 160943db362dSMaciej Żenczykowski err = move_addr_to_kernel(uservaddr, addrlen, &address); 16101da177e4SLinus Torvalds if (err < 0) 16111da177e4SLinus Torvalds goto out_put; 16121da177e4SLinus Torvalds 161389bddce5SStephen Hemminger err = 1614230b1839SYOSHIFUJI Hideaki security_socket_connect(sock, (struct sockaddr *)&address, addrlen); 16151da177e4SLinus Torvalds if (err) 16161da177e4SLinus Torvalds goto out_put; 16171da177e4SLinus Torvalds 1618230b1839SYOSHIFUJI Hideaki err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, 16191da177e4SLinus Torvalds sock->file->f_flags); 16201da177e4SLinus Torvalds out_put: 16216cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16221da177e4SLinus Torvalds out: 16231da177e4SLinus Torvalds return err; 16241da177e4SLinus Torvalds } 16251da177e4SLinus Torvalds 16261da177e4SLinus Torvalds /* 16271da177e4SLinus Torvalds * Get the local address ('name') of a socket object. Move the obtained 16281da177e4SLinus Torvalds * name to user space. 16291da177e4SLinus Torvalds */ 16301da177e4SLinus Torvalds 163120f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr, 163220f37034SHeiko Carstens int __user *, usockaddr_len) 16331da177e4SLinus Torvalds { 16341da177e4SLinus Torvalds struct socket *sock; 1635230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16366cb153caSBenjamin LaHaise int len, err, fput_needed; 16371da177e4SLinus Torvalds 16386cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16391da177e4SLinus Torvalds if (!sock) 16401da177e4SLinus Torvalds goto out; 16411da177e4SLinus Torvalds 16421da177e4SLinus Torvalds err = security_socket_getsockname(sock); 16431da177e4SLinus Torvalds if (err) 16441da177e4SLinus Torvalds goto out_put; 16451da177e4SLinus Torvalds 1646230b1839SYOSHIFUJI Hideaki err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0); 16471da177e4SLinus Torvalds if (err) 16481da177e4SLinus Torvalds goto out_put; 164943db362dSMaciej Żenczykowski err = move_addr_to_user(&address, len, usockaddr, usockaddr_len); 16501da177e4SLinus Torvalds 16511da177e4SLinus Torvalds out_put: 16526cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16531da177e4SLinus Torvalds out: 16541da177e4SLinus Torvalds return err; 16551da177e4SLinus Torvalds } 16561da177e4SLinus Torvalds 16571da177e4SLinus Torvalds /* 16581da177e4SLinus Torvalds * Get the remote address ('name') of a socket object. Move the obtained 16591da177e4SLinus Torvalds * name to user space. 16601da177e4SLinus Torvalds */ 16611da177e4SLinus Torvalds 166220f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, 166320f37034SHeiko Carstens int __user *, usockaddr_len) 16641da177e4SLinus Torvalds { 16651da177e4SLinus Torvalds struct socket *sock; 1666230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16676cb153caSBenjamin LaHaise int len, err, fput_needed; 16681da177e4SLinus Torvalds 166989bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 167089bddce5SStephen Hemminger if (sock != NULL) { 16711da177e4SLinus Torvalds err = security_socket_getpeername(sock); 16721da177e4SLinus Torvalds if (err) { 16736cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16741da177e4SLinus Torvalds return err; 16751da177e4SLinus Torvalds } 16761da177e4SLinus Torvalds 167789bddce5SStephen Hemminger err = 1678230b1839SYOSHIFUJI Hideaki sock->ops->getname(sock, (struct sockaddr *)&address, &len, 167989bddce5SStephen Hemminger 1); 16801da177e4SLinus Torvalds if (!err) 168143db362dSMaciej Żenczykowski err = move_addr_to_user(&address, len, usockaddr, 168289bddce5SStephen Hemminger usockaddr_len); 16836cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16841da177e4SLinus Torvalds } 16851da177e4SLinus Torvalds return err; 16861da177e4SLinus Torvalds } 16871da177e4SLinus Torvalds 16881da177e4SLinus Torvalds /* 16891da177e4SLinus Torvalds * Send a datagram to a given address. We move the address into kernel 16901da177e4SLinus Torvalds * space and check the user space data area is readable before invoking 16911da177e4SLinus Torvalds * the protocol. 16921da177e4SLinus Torvalds */ 16931da177e4SLinus Torvalds 16943e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, 169595c96174SEric Dumazet unsigned int, flags, struct sockaddr __user *, addr, 16963e0fa65fSHeiko Carstens int, addr_len) 16971da177e4SLinus Torvalds { 16981da177e4SLinus Torvalds struct socket *sock; 1699230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17001da177e4SLinus Torvalds int err; 17011da177e4SLinus Torvalds struct msghdr msg; 17021da177e4SLinus Torvalds struct iovec iov; 17036cb153caSBenjamin LaHaise int fput_needed; 17041da177e4SLinus Torvalds 1705253eacc0SLinus Torvalds if (len > INT_MAX) 1706253eacc0SLinus Torvalds len = INT_MAX; 1707de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 1708de0fa95cSPavel Emelyanov if (!sock) 17094387ff75SDavid S. Miller goto out; 17106cb153caSBenjamin LaHaise 17111da177e4SLinus Torvalds iov.iov_base = buff; 17121da177e4SLinus Torvalds iov.iov_len = len; 17131da177e4SLinus Torvalds msg.msg_name = NULL; 17141da177e4SLinus Torvalds msg.msg_iov = &iov; 17151da177e4SLinus Torvalds msg.msg_iovlen = 1; 17161da177e4SLinus Torvalds msg.msg_control = NULL; 17171da177e4SLinus Torvalds msg.msg_controllen = 0; 17181da177e4SLinus Torvalds msg.msg_namelen = 0; 17196cb153caSBenjamin LaHaise if (addr) { 172043db362dSMaciej Żenczykowski err = move_addr_to_kernel(addr, addr_len, &address); 17211da177e4SLinus Torvalds if (err < 0) 17221da177e4SLinus Torvalds goto out_put; 1723230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 17241da177e4SLinus Torvalds msg.msg_namelen = addr_len; 17251da177e4SLinus Torvalds } 17261da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 17271da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 17281da177e4SLinus Torvalds msg.msg_flags = flags; 17291da177e4SLinus Torvalds err = sock_sendmsg(sock, &msg, len); 17301da177e4SLinus Torvalds 17311da177e4SLinus Torvalds out_put: 1732de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 17334387ff75SDavid S. Miller out: 17341da177e4SLinus Torvalds return err; 17351da177e4SLinus Torvalds } 17361da177e4SLinus Torvalds 17371da177e4SLinus Torvalds /* 17381da177e4SLinus Torvalds * Send a datagram down a socket. 17391da177e4SLinus Torvalds */ 17401da177e4SLinus Torvalds 17413e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, 174295c96174SEric Dumazet unsigned int, flags) 17431da177e4SLinus Torvalds { 17441da177e4SLinus Torvalds return sys_sendto(fd, buff, len, flags, NULL, 0); 17451da177e4SLinus Torvalds } 17461da177e4SLinus Torvalds 17471da177e4SLinus Torvalds /* 17481da177e4SLinus Torvalds * Receive a frame from the socket and optionally record the address of the 17491da177e4SLinus Torvalds * sender. We verify the buffers are writable and if needed move the 17501da177e4SLinus Torvalds * sender address from kernel to user space. 17511da177e4SLinus Torvalds */ 17521da177e4SLinus Torvalds 17533e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, 175495c96174SEric Dumazet unsigned int, flags, struct sockaddr __user *, addr, 17553e0fa65fSHeiko Carstens int __user *, addr_len) 17561da177e4SLinus Torvalds { 17571da177e4SLinus Torvalds struct socket *sock; 17581da177e4SLinus Torvalds struct iovec iov; 17591da177e4SLinus Torvalds struct msghdr msg; 1760230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17611da177e4SLinus Torvalds int err, err2; 17626cb153caSBenjamin LaHaise int fput_needed; 17631da177e4SLinus Torvalds 1764253eacc0SLinus Torvalds if (size > INT_MAX) 1765253eacc0SLinus Torvalds size = INT_MAX; 1766de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 17671da177e4SLinus Torvalds if (!sock) 1768de0fa95cSPavel Emelyanov goto out; 17691da177e4SLinus Torvalds 17701da177e4SLinus Torvalds msg.msg_control = NULL; 17711da177e4SLinus Torvalds msg.msg_controllen = 0; 17721da177e4SLinus Torvalds msg.msg_iovlen = 1; 17731da177e4SLinus Torvalds msg.msg_iov = &iov; 17741da177e4SLinus Torvalds iov.iov_len = size; 17751da177e4SLinus Torvalds iov.iov_base = ubuf; 1776230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 1777230b1839SYOSHIFUJI Hideaki msg.msg_namelen = sizeof(address); 17781da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 17791da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 17801da177e4SLinus Torvalds err = sock_recvmsg(sock, &msg, size, flags); 17811da177e4SLinus Torvalds 178289bddce5SStephen Hemminger if (err >= 0 && addr != NULL) { 178343db362dSMaciej Żenczykowski err2 = move_addr_to_user(&address, 1784230b1839SYOSHIFUJI Hideaki msg.msg_namelen, addr, addr_len); 17851da177e4SLinus Torvalds if (err2 < 0) 17861da177e4SLinus Torvalds err = err2; 17871da177e4SLinus Torvalds } 1788de0fa95cSPavel Emelyanov 1789de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 17904387ff75SDavid S. Miller out: 17911da177e4SLinus Torvalds return err; 17921da177e4SLinus Torvalds } 17931da177e4SLinus Torvalds 17941da177e4SLinus Torvalds /* 17951da177e4SLinus Torvalds * Receive a datagram from a socket. 17961da177e4SLinus Torvalds */ 17971da177e4SLinus Torvalds 179889bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size, 179995c96174SEric Dumazet unsigned int flags) 18001da177e4SLinus Torvalds { 18011da177e4SLinus Torvalds return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); 18021da177e4SLinus Torvalds } 18031da177e4SLinus Torvalds 18041da177e4SLinus Torvalds /* 18051da177e4SLinus Torvalds * Set a socket option. Because we don't know the option lengths we have 18061da177e4SLinus Torvalds * to pass the user mode parameter for the protocols to sort out. 18071da177e4SLinus Torvalds */ 18081da177e4SLinus Torvalds 180920f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, 181020f37034SHeiko Carstens char __user *, optval, int, optlen) 18111da177e4SLinus Torvalds { 18126cb153caSBenjamin LaHaise int err, fput_needed; 18131da177e4SLinus Torvalds struct socket *sock; 18141da177e4SLinus Torvalds 18151da177e4SLinus Torvalds if (optlen < 0) 18161da177e4SLinus Torvalds return -EINVAL; 18171da177e4SLinus Torvalds 181889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 181989bddce5SStephen Hemminger if (sock != NULL) { 18201da177e4SLinus Torvalds err = security_socket_setsockopt(sock, level, optname); 18216cb153caSBenjamin LaHaise if (err) 18226cb153caSBenjamin LaHaise goto out_put; 18231da177e4SLinus Torvalds 18241da177e4SLinus Torvalds if (level == SOL_SOCKET) 182589bddce5SStephen Hemminger err = 182689bddce5SStephen Hemminger sock_setsockopt(sock, level, optname, optval, 182789bddce5SStephen Hemminger optlen); 18281da177e4SLinus Torvalds else 182989bddce5SStephen Hemminger err = 183089bddce5SStephen Hemminger sock->ops->setsockopt(sock, level, optname, optval, 183189bddce5SStephen Hemminger optlen); 18326cb153caSBenjamin LaHaise out_put: 18336cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18341da177e4SLinus Torvalds } 18351da177e4SLinus Torvalds return err; 18361da177e4SLinus Torvalds } 18371da177e4SLinus Torvalds 18381da177e4SLinus Torvalds /* 18391da177e4SLinus Torvalds * Get a socket option. Because we don't know the option lengths we have 18401da177e4SLinus Torvalds * to pass a user mode parameter for the protocols to sort out. 18411da177e4SLinus Torvalds */ 18421da177e4SLinus Torvalds 184320f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, 184420f37034SHeiko Carstens char __user *, optval, int __user *, optlen) 18451da177e4SLinus Torvalds { 18466cb153caSBenjamin LaHaise int err, fput_needed; 18471da177e4SLinus Torvalds struct socket *sock; 18481da177e4SLinus Torvalds 184989bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 185089bddce5SStephen Hemminger if (sock != NULL) { 18516cb153caSBenjamin LaHaise err = security_socket_getsockopt(sock, level, optname); 18526cb153caSBenjamin LaHaise if (err) 18536cb153caSBenjamin LaHaise goto out_put; 18541da177e4SLinus Torvalds 18551da177e4SLinus Torvalds if (level == SOL_SOCKET) 185689bddce5SStephen Hemminger err = 185789bddce5SStephen Hemminger sock_getsockopt(sock, level, optname, optval, 185889bddce5SStephen Hemminger optlen); 18591da177e4SLinus Torvalds else 186089bddce5SStephen Hemminger err = 186189bddce5SStephen Hemminger sock->ops->getsockopt(sock, level, optname, optval, 186289bddce5SStephen Hemminger optlen); 18636cb153caSBenjamin LaHaise out_put: 18646cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18651da177e4SLinus Torvalds } 18661da177e4SLinus Torvalds return err; 18671da177e4SLinus Torvalds } 18681da177e4SLinus Torvalds 18691da177e4SLinus Torvalds /* 18701da177e4SLinus Torvalds * Shutdown a socket. 18711da177e4SLinus Torvalds */ 18721da177e4SLinus Torvalds 1873754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how) 18741da177e4SLinus Torvalds { 18756cb153caSBenjamin LaHaise int err, fput_needed; 18761da177e4SLinus Torvalds struct socket *sock; 18771da177e4SLinus Torvalds 187889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 187989bddce5SStephen Hemminger if (sock != NULL) { 18801da177e4SLinus Torvalds err = security_socket_shutdown(sock, how); 18816cb153caSBenjamin LaHaise if (!err) 18821da177e4SLinus Torvalds err = sock->ops->shutdown(sock, how); 18836cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18841da177e4SLinus Torvalds } 18851da177e4SLinus Torvalds return err; 18861da177e4SLinus Torvalds } 18871da177e4SLinus Torvalds 18881da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit 18891da177e4SLinus Torvalds * fields which are the same type (int / unsigned) on our platforms. 18901da177e4SLinus Torvalds */ 18911da177e4SLinus Torvalds #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) 18921da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) 18931da177e4SLinus Torvalds #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) 18941da177e4SLinus Torvalds 1895c71d8ebeSTetsuo Handa struct used_address { 1896c71d8ebeSTetsuo Handa struct sockaddr_storage name; 1897c71d8ebeSTetsuo Handa unsigned int name_len; 1898c71d8ebeSTetsuo Handa }; 1899c71d8ebeSTetsuo Handa 1900228e548eSAnton Blanchard static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, 190195c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, 1902c71d8ebeSTetsuo Handa struct used_address *used_address) 19031da177e4SLinus Torvalds { 190489bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 190589bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 1906230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 19071da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 1908b9d717a7SAlex Williamson unsigned char ctl[sizeof(struct cmsghdr) + 20] 1909b9d717a7SAlex Williamson __attribute__ ((aligned(sizeof(__kernel_size_t)))); 1910b9d717a7SAlex Williamson /* 20 is size of ipv6_pktinfo */ 19111da177e4SLinus Torvalds unsigned char *ctl_buf = ctl; 1912a74e9106SEric Dumazet int err, ctl_len, total_len; 19131da177e4SLinus Torvalds 19141da177e4SLinus Torvalds err = -EFAULT; 19151da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) { 1916228e548eSAnton Blanchard if (get_compat_msghdr(msg_sys, msg_compat)) 19171da177e4SLinus Torvalds return -EFAULT; 1918228e548eSAnton Blanchard } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) 19191da177e4SLinus Torvalds return -EFAULT; 19201da177e4SLinus Torvalds 1921a74e9106SEric Dumazet if (msg_sys->msg_iovlen > UIO_FASTIOV) { 19221da177e4SLinus Torvalds err = -EMSGSIZE; 1923228e548eSAnton Blanchard if (msg_sys->msg_iovlen > UIO_MAXIOV) 1924228e548eSAnton Blanchard goto out; 19251da177e4SLinus Torvalds err = -ENOMEM; 1926a74e9106SEric Dumazet iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec), 1927a74e9106SEric Dumazet GFP_KERNEL); 19281da177e4SLinus Torvalds if (!iov) 1929228e548eSAnton Blanchard goto out; 19301da177e4SLinus Torvalds } 19311da177e4SLinus Torvalds 19321da177e4SLinus Torvalds /* This will also move the address data into kernel space */ 19331da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) { 193443db362dSMaciej Żenczykowski err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ); 19351da177e4SLinus Torvalds } else 193643db362dSMaciej Żenczykowski err = verify_iovec(msg_sys, iov, &address, VERIFY_READ); 19371da177e4SLinus Torvalds if (err < 0) 19381da177e4SLinus Torvalds goto out_freeiov; 19391da177e4SLinus Torvalds total_len = err; 19401da177e4SLinus Torvalds 19411da177e4SLinus Torvalds err = -ENOBUFS; 19421da177e4SLinus Torvalds 1943228e548eSAnton Blanchard if (msg_sys->msg_controllen > INT_MAX) 19441da177e4SLinus Torvalds goto out_freeiov; 1945228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 19461da177e4SLinus Torvalds if ((MSG_CMSG_COMPAT & flags) && ctl_len) { 194789bddce5SStephen Hemminger err = 1948228e548eSAnton Blanchard cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, 194989bddce5SStephen Hemminger sizeof(ctl)); 19501da177e4SLinus Torvalds if (err) 19511da177e4SLinus Torvalds goto out_freeiov; 1952228e548eSAnton Blanchard ctl_buf = msg_sys->msg_control; 1953228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 19541da177e4SLinus Torvalds } else if (ctl_len) { 195589bddce5SStephen Hemminger if (ctl_len > sizeof(ctl)) { 19561da177e4SLinus Torvalds ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); 19571da177e4SLinus Torvalds if (ctl_buf == NULL) 19581da177e4SLinus Torvalds goto out_freeiov; 19591da177e4SLinus Torvalds } 19601da177e4SLinus Torvalds err = -EFAULT; 19611da177e4SLinus Torvalds /* 1962228e548eSAnton Blanchard * Careful! Before this, msg_sys->msg_control contains a user pointer. 19631da177e4SLinus Torvalds * Afterwards, it will be a kernel pointer. Thus the compiler-assisted 19641da177e4SLinus Torvalds * checking falls down on this. 19651da177e4SLinus Torvalds */ 1966fb8621bbSNamhyung Kim if (copy_from_user(ctl_buf, 1967228e548eSAnton Blanchard (void __user __force *)msg_sys->msg_control, 196889bddce5SStephen Hemminger ctl_len)) 19691da177e4SLinus Torvalds goto out_freectl; 1970228e548eSAnton Blanchard msg_sys->msg_control = ctl_buf; 19711da177e4SLinus Torvalds } 1972228e548eSAnton Blanchard msg_sys->msg_flags = flags; 19731da177e4SLinus Torvalds 19741da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 1975228e548eSAnton Blanchard msg_sys->msg_flags |= MSG_DONTWAIT; 1976c71d8ebeSTetsuo Handa /* 1977c71d8ebeSTetsuo Handa * If this is sendmmsg() and current destination address is same as 1978c71d8ebeSTetsuo Handa * previously succeeded address, omit asking LSM's decision. 1979c71d8ebeSTetsuo Handa * used_address->name_len is initialized to UINT_MAX so that the first 1980c71d8ebeSTetsuo Handa * destination address never matches. 1981c71d8ebeSTetsuo Handa */ 1982bc909d9dSMathieu Desnoyers if (used_address && msg_sys->msg_name && 1983bc909d9dSMathieu Desnoyers used_address->name_len == msg_sys->msg_namelen && 1984bc909d9dSMathieu Desnoyers !memcmp(&used_address->name, msg_sys->msg_name, 1985c71d8ebeSTetsuo Handa used_address->name_len)) { 1986c71d8ebeSTetsuo Handa err = sock_sendmsg_nosec(sock, msg_sys, total_len); 1987c71d8ebeSTetsuo Handa goto out_freectl; 1988c71d8ebeSTetsuo Handa } 1989c71d8ebeSTetsuo Handa err = sock_sendmsg(sock, msg_sys, total_len); 1990c71d8ebeSTetsuo Handa /* 1991c71d8ebeSTetsuo Handa * If this is sendmmsg() and sending to current destination address was 1992c71d8ebeSTetsuo Handa * successful, remember it. 1993c71d8ebeSTetsuo Handa */ 1994c71d8ebeSTetsuo Handa if (used_address && err >= 0) { 1995c71d8ebeSTetsuo Handa used_address->name_len = msg_sys->msg_namelen; 1996bc909d9dSMathieu Desnoyers if (msg_sys->msg_name) 1997bc909d9dSMathieu Desnoyers memcpy(&used_address->name, msg_sys->msg_name, 1998c71d8ebeSTetsuo Handa used_address->name_len); 1999c71d8ebeSTetsuo Handa } 20001da177e4SLinus Torvalds 20011da177e4SLinus Torvalds out_freectl: 20021da177e4SLinus Torvalds if (ctl_buf != ctl) 20031da177e4SLinus Torvalds sock_kfree_s(sock->sk, ctl_buf, ctl_len); 20041da177e4SLinus Torvalds out_freeiov: 20051da177e4SLinus Torvalds if (iov != iovstack) 2006a74e9106SEric Dumazet kfree(iov); 2007228e548eSAnton Blanchard out: 2008228e548eSAnton Blanchard return err; 2009228e548eSAnton Blanchard } 2010228e548eSAnton Blanchard 2011228e548eSAnton Blanchard /* 2012228e548eSAnton Blanchard * BSD sendmsg interface 2013228e548eSAnton Blanchard */ 2014228e548eSAnton Blanchard 201595c96174SEric Dumazet SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags) 2016228e548eSAnton Blanchard { 2017228e548eSAnton Blanchard int fput_needed, err; 2018228e548eSAnton Blanchard struct msghdr msg_sys; 2019228e548eSAnton Blanchard struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); 2020228e548eSAnton Blanchard 2021228e548eSAnton Blanchard if (!sock) 2022228e548eSAnton Blanchard goto out; 2023228e548eSAnton Blanchard 2024c71d8ebeSTetsuo Handa err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL); 2025228e548eSAnton Blanchard 20266cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 20271da177e4SLinus Torvalds out: 20281da177e4SLinus Torvalds return err; 20291da177e4SLinus Torvalds } 20301da177e4SLinus Torvalds 2031228e548eSAnton Blanchard /* 2032228e548eSAnton Blanchard * Linux sendmmsg interface 2033228e548eSAnton Blanchard */ 2034228e548eSAnton Blanchard 2035228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2036228e548eSAnton Blanchard unsigned int flags) 2037228e548eSAnton Blanchard { 2038228e548eSAnton Blanchard int fput_needed, err, datagrams; 2039228e548eSAnton Blanchard struct socket *sock; 2040228e548eSAnton Blanchard struct mmsghdr __user *entry; 2041228e548eSAnton Blanchard struct compat_mmsghdr __user *compat_entry; 2042228e548eSAnton Blanchard struct msghdr msg_sys; 2043c71d8ebeSTetsuo Handa struct used_address used_address; 2044228e548eSAnton Blanchard 204598382f41SAnton Blanchard if (vlen > UIO_MAXIOV) 204698382f41SAnton Blanchard vlen = UIO_MAXIOV; 2047228e548eSAnton Blanchard 2048228e548eSAnton Blanchard datagrams = 0; 2049228e548eSAnton Blanchard 2050228e548eSAnton Blanchard sock = sockfd_lookup_light(fd, &err, &fput_needed); 2051228e548eSAnton Blanchard if (!sock) 2052228e548eSAnton Blanchard return err; 2053228e548eSAnton Blanchard 2054c71d8ebeSTetsuo Handa used_address.name_len = UINT_MAX; 2055228e548eSAnton Blanchard entry = mmsg; 2056228e548eSAnton Blanchard compat_entry = (struct compat_mmsghdr __user *)mmsg; 2057728ffb86SAnton Blanchard err = 0; 2058228e548eSAnton Blanchard 2059228e548eSAnton Blanchard while (datagrams < vlen) { 2060228e548eSAnton Blanchard if (MSG_CMSG_COMPAT & flags) { 2061228e548eSAnton Blanchard err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, 2062c71d8ebeSTetsuo Handa &msg_sys, flags, &used_address); 2063228e548eSAnton Blanchard if (err < 0) 2064228e548eSAnton Blanchard break; 2065228e548eSAnton Blanchard err = __put_user(err, &compat_entry->msg_len); 2066228e548eSAnton Blanchard ++compat_entry; 2067228e548eSAnton Blanchard } else { 2068228e548eSAnton Blanchard err = __sys_sendmsg(sock, (struct msghdr __user *)entry, 2069c71d8ebeSTetsuo Handa &msg_sys, flags, &used_address); 2070228e548eSAnton Blanchard if (err < 0) 2071228e548eSAnton Blanchard break; 2072228e548eSAnton Blanchard err = put_user(err, &entry->msg_len); 2073228e548eSAnton Blanchard ++entry; 2074228e548eSAnton Blanchard } 2075228e548eSAnton Blanchard 2076228e548eSAnton Blanchard if (err) 2077228e548eSAnton Blanchard break; 2078228e548eSAnton Blanchard ++datagrams; 2079228e548eSAnton Blanchard } 2080228e548eSAnton Blanchard 2081228e548eSAnton Blanchard fput_light(sock->file, fput_needed); 2082228e548eSAnton Blanchard 2083728ffb86SAnton Blanchard /* We only return an error if no datagrams were able to be sent */ 2084728ffb86SAnton Blanchard if (datagrams != 0) 2085228e548eSAnton Blanchard return datagrams; 2086228e548eSAnton Blanchard 2087228e548eSAnton Blanchard return err; 2088228e548eSAnton Blanchard } 2089228e548eSAnton Blanchard 2090228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, 2091228e548eSAnton Blanchard unsigned int, vlen, unsigned int, flags) 2092228e548eSAnton Blanchard { 2093228e548eSAnton Blanchard return __sys_sendmmsg(fd, mmsg, vlen, flags); 2094228e548eSAnton Blanchard } 2095228e548eSAnton Blanchard 2096a2e27255SArnaldo Carvalho de Melo static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, 209795c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, int nosec) 20981da177e4SLinus Torvalds { 209989bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 210089bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 21011da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV]; 21021da177e4SLinus Torvalds struct iovec *iov = iovstack; 21031da177e4SLinus Torvalds unsigned long cmsg_ptr; 2104a74e9106SEric Dumazet int err, total_len, len; 21051da177e4SLinus Torvalds 21061da177e4SLinus Torvalds /* kernel mode address */ 2107230b1839SYOSHIFUJI Hideaki struct sockaddr_storage addr; 21081da177e4SLinus Torvalds 21091da177e4SLinus Torvalds /* user mode address pointers */ 21101da177e4SLinus Torvalds struct sockaddr __user *uaddr; 21111da177e4SLinus Torvalds int __user *uaddr_len; 21121da177e4SLinus Torvalds 21131da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) { 2114a2e27255SArnaldo Carvalho de Melo if (get_compat_msghdr(msg_sys, msg_compat)) 21151da177e4SLinus Torvalds return -EFAULT; 2116c6d409cfSEric Dumazet } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) 21171da177e4SLinus Torvalds return -EFAULT; 21181da177e4SLinus Torvalds 2119a74e9106SEric Dumazet if (msg_sys->msg_iovlen > UIO_FASTIOV) { 21201da177e4SLinus Torvalds err = -EMSGSIZE; 2121a2e27255SArnaldo Carvalho de Melo if (msg_sys->msg_iovlen > UIO_MAXIOV) 2122a2e27255SArnaldo Carvalho de Melo goto out; 21231da177e4SLinus Torvalds err = -ENOMEM; 2124a74e9106SEric Dumazet iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec), 2125a74e9106SEric Dumazet GFP_KERNEL); 21261da177e4SLinus Torvalds if (!iov) 2127a2e27255SArnaldo Carvalho de Melo goto out; 21281da177e4SLinus Torvalds } 21291da177e4SLinus Torvalds 21301da177e4SLinus Torvalds /* 21311da177e4SLinus Torvalds * Save the user-mode address (verify_iovec will change the 21321da177e4SLinus Torvalds * kernel msghdr to use the kernel address space) 21331da177e4SLinus Torvalds */ 21341da177e4SLinus Torvalds 2135a2e27255SArnaldo Carvalho de Melo uaddr = (__force void __user *)msg_sys->msg_name; 21361da177e4SLinus Torvalds uaddr_len = COMPAT_NAMELEN(msg); 21371da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) { 213843db362dSMaciej Żenczykowski err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE); 21391da177e4SLinus Torvalds } else 214043db362dSMaciej Żenczykowski err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE); 21411da177e4SLinus Torvalds if (err < 0) 21421da177e4SLinus Torvalds goto out_freeiov; 21431da177e4SLinus Torvalds total_len = err; 21441da177e4SLinus Torvalds 2145a2e27255SArnaldo Carvalho de Melo cmsg_ptr = (unsigned long)msg_sys->msg_control; 2146a2e27255SArnaldo Carvalho de Melo msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 21471da177e4SLinus Torvalds 21481da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 21491da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 2150a2e27255SArnaldo Carvalho de Melo err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, 2151a2e27255SArnaldo Carvalho de Melo total_len, flags); 21521da177e4SLinus Torvalds if (err < 0) 21531da177e4SLinus Torvalds goto out_freeiov; 21541da177e4SLinus Torvalds len = err; 21551da177e4SLinus Torvalds 21561da177e4SLinus Torvalds if (uaddr != NULL) { 215743db362dSMaciej Żenczykowski err = move_addr_to_user(&addr, 2158a2e27255SArnaldo Carvalho de Melo msg_sys->msg_namelen, uaddr, 215989bddce5SStephen Hemminger uaddr_len); 21601da177e4SLinus Torvalds if (err < 0) 21611da177e4SLinus Torvalds goto out_freeiov; 21621da177e4SLinus Torvalds } 2163a2e27255SArnaldo Carvalho de Melo err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT), 216437f7f421SDavid S. Miller COMPAT_FLAGS(msg)); 21651da177e4SLinus Torvalds if (err) 21661da177e4SLinus Torvalds goto out_freeiov; 21671da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) 2168a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 21691da177e4SLinus Torvalds &msg_compat->msg_controllen); 21701da177e4SLinus Torvalds else 2171a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 21721da177e4SLinus Torvalds &msg->msg_controllen); 21731da177e4SLinus Torvalds if (err) 21741da177e4SLinus Torvalds goto out_freeiov; 21751da177e4SLinus Torvalds err = len; 21761da177e4SLinus Torvalds 21771da177e4SLinus Torvalds out_freeiov: 21781da177e4SLinus Torvalds if (iov != iovstack) 2179a74e9106SEric Dumazet kfree(iov); 2180a2e27255SArnaldo Carvalho de Melo out: 2181a2e27255SArnaldo Carvalho de Melo return err; 2182a2e27255SArnaldo Carvalho de Melo } 2183a2e27255SArnaldo Carvalho de Melo 2184a2e27255SArnaldo Carvalho de Melo /* 2185a2e27255SArnaldo Carvalho de Melo * BSD recvmsg interface 2186a2e27255SArnaldo Carvalho de Melo */ 2187a2e27255SArnaldo Carvalho de Melo 2188a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, 2189a2e27255SArnaldo Carvalho de Melo unsigned int, flags) 2190a2e27255SArnaldo Carvalho de Melo { 2191a2e27255SArnaldo Carvalho de Melo int fput_needed, err; 2192a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2193a2e27255SArnaldo Carvalho de Melo struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); 2194a2e27255SArnaldo Carvalho de Melo 2195a2e27255SArnaldo Carvalho de Melo if (!sock) 2196a2e27255SArnaldo Carvalho de Melo goto out; 2197a2e27255SArnaldo Carvalho de Melo 2198a2e27255SArnaldo Carvalho de Melo err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2199a2e27255SArnaldo Carvalho de Melo 22006cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 22011da177e4SLinus Torvalds out: 22021da177e4SLinus Torvalds return err; 22031da177e4SLinus Torvalds } 22041da177e4SLinus Torvalds 2205a2e27255SArnaldo Carvalho de Melo /* 2206a2e27255SArnaldo Carvalho de Melo * Linux recvmmsg interface 2207a2e27255SArnaldo Carvalho de Melo */ 22081da177e4SLinus Torvalds 2209a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2210a2e27255SArnaldo Carvalho de Melo unsigned int flags, struct timespec *timeout) 2211a2e27255SArnaldo Carvalho de Melo { 2212a2e27255SArnaldo Carvalho de Melo int fput_needed, err, datagrams; 2213a2e27255SArnaldo Carvalho de Melo struct socket *sock; 2214a2e27255SArnaldo Carvalho de Melo struct mmsghdr __user *entry; 2215d7256d0eSJean-Mickael Guerin struct compat_mmsghdr __user *compat_entry; 2216a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2217a2e27255SArnaldo Carvalho de Melo struct timespec end_time; 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) { 2242d7256d0eSJean-Mickael Guerin err = __sys_recvmsg(sock, (struct 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 { 2250a2e27255SArnaldo Carvalho de Melo err = __sys_recvmsg(sock, (struct msghdr __user *)entry, 2251b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2252b9eb8b87SAnton Blanchard datagrams); 2253a2e27255SArnaldo Carvalho de Melo if (err < 0) 2254a2e27255SArnaldo Carvalho de Melo break; 2255a2e27255SArnaldo Carvalho de Melo err = put_user(err, &entry->msg_len); 2256d7256d0eSJean-Mickael Guerin ++entry; 2257d7256d0eSJean-Mickael Guerin } 2258d7256d0eSJean-Mickael Guerin 2259a2e27255SArnaldo Carvalho de Melo if (err) 2260a2e27255SArnaldo Carvalho de Melo break; 2261a2e27255SArnaldo Carvalho de Melo ++datagrams; 2262a2e27255SArnaldo Carvalho de Melo 226371c5c159SBrandon L Black /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ 226471c5c159SBrandon L Black if (flags & MSG_WAITFORONE) 226571c5c159SBrandon L Black flags |= MSG_DONTWAIT; 226671c5c159SBrandon L Black 2267a2e27255SArnaldo Carvalho de Melo if (timeout) { 2268a2e27255SArnaldo Carvalho de Melo ktime_get_ts(timeout); 2269a2e27255SArnaldo Carvalho de Melo *timeout = timespec_sub(end_time, *timeout); 2270a2e27255SArnaldo Carvalho de Melo if (timeout->tv_sec < 0) { 2271a2e27255SArnaldo Carvalho de Melo timeout->tv_sec = timeout->tv_nsec = 0; 2272a2e27255SArnaldo Carvalho de Melo break; 2273a2e27255SArnaldo Carvalho de Melo } 2274a2e27255SArnaldo Carvalho de Melo 2275a2e27255SArnaldo Carvalho de Melo /* Timeout, return less than vlen datagrams */ 2276a2e27255SArnaldo Carvalho de Melo if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) 2277a2e27255SArnaldo Carvalho de Melo break; 2278a2e27255SArnaldo Carvalho de Melo } 2279a2e27255SArnaldo Carvalho de Melo 2280a2e27255SArnaldo Carvalho de Melo /* Out of band data, return right away */ 2281a2e27255SArnaldo Carvalho de Melo if (msg_sys.msg_flags & MSG_OOB) 2282a2e27255SArnaldo Carvalho de Melo break; 2283a2e27255SArnaldo Carvalho de Melo } 2284a2e27255SArnaldo Carvalho de Melo 2285a2e27255SArnaldo Carvalho de Melo out_put: 2286a2e27255SArnaldo Carvalho de Melo fput_light(sock->file, fput_needed); 2287a2e27255SArnaldo Carvalho de Melo 2288a2e27255SArnaldo Carvalho de Melo if (err == 0) 2289a2e27255SArnaldo Carvalho de Melo return datagrams; 2290a2e27255SArnaldo Carvalho de Melo 2291a2e27255SArnaldo Carvalho de Melo if (datagrams != 0) { 2292a2e27255SArnaldo Carvalho de Melo /* 2293a2e27255SArnaldo Carvalho de Melo * We may return less entries than requested (vlen) if the 2294a2e27255SArnaldo Carvalho de Melo * sock is non block and there aren't enough datagrams... 2295a2e27255SArnaldo Carvalho de Melo */ 2296a2e27255SArnaldo Carvalho de Melo if (err != -EAGAIN) { 2297a2e27255SArnaldo Carvalho de Melo /* 2298a2e27255SArnaldo Carvalho de Melo * ... or if recvmsg returns an error after we 2299a2e27255SArnaldo Carvalho de Melo * received some datagrams, where we record the 2300a2e27255SArnaldo Carvalho de Melo * error to return on the next call or if the 2301a2e27255SArnaldo Carvalho de Melo * app asks about it using getsockopt(SO_ERROR). 2302a2e27255SArnaldo Carvalho de Melo */ 2303a2e27255SArnaldo Carvalho de Melo sock->sk->sk_err = -err; 2304a2e27255SArnaldo Carvalho de Melo } 2305a2e27255SArnaldo Carvalho de Melo 2306a2e27255SArnaldo Carvalho de Melo return datagrams; 2307a2e27255SArnaldo Carvalho de Melo } 2308a2e27255SArnaldo Carvalho de Melo 2309a2e27255SArnaldo Carvalho de Melo return err; 2310a2e27255SArnaldo Carvalho de Melo } 2311a2e27255SArnaldo Carvalho de Melo 2312a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, 2313a2e27255SArnaldo Carvalho de Melo unsigned int, vlen, unsigned int, flags, 2314a2e27255SArnaldo Carvalho de Melo struct timespec __user *, timeout) 2315a2e27255SArnaldo Carvalho de Melo { 2316a2e27255SArnaldo Carvalho de Melo int datagrams; 2317a2e27255SArnaldo Carvalho de Melo struct timespec timeout_sys; 2318a2e27255SArnaldo Carvalho de Melo 2319a2e27255SArnaldo Carvalho de Melo if (!timeout) 2320a2e27255SArnaldo Carvalho de Melo return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); 2321a2e27255SArnaldo Carvalho de Melo 2322a2e27255SArnaldo Carvalho de Melo if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys))) 2323a2e27255SArnaldo Carvalho de Melo return -EFAULT; 2324a2e27255SArnaldo Carvalho de Melo 2325a2e27255SArnaldo Carvalho de Melo datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys); 2326a2e27255SArnaldo Carvalho de Melo 2327a2e27255SArnaldo Carvalho de Melo if (datagrams > 0 && 2328a2e27255SArnaldo Carvalho de Melo copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys))) 2329a2e27255SArnaldo Carvalho de Melo datagrams = -EFAULT; 2330a2e27255SArnaldo Carvalho de Melo 2331a2e27255SArnaldo Carvalho de Melo return datagrams; 2332a2e27255SArnaldo Carvalho de Melo } 2333a2e27255SArnaldo Carvalho de Melo 2334a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL 23351da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */ 23361da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long)) 2337228e548eSAnton Blanchard static const unsigned char nargs[21] = { 233889bddce5SStephen Hemminger AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 23391da177e4SLinus Torvalds AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 2340aaca0bdcSUlrich Drepper AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 2341228e548eSAnton Blanchard AL(4), AL(5), AL(4) 234289bddce5SStephen Hemminger }; 234389bddce5SStephen Hemminger 23441da177e4SLinus Torvalds #undef AL 23451da177e4SLinus Torvalds 23461da177e4SLinus Torvalds /* 23471da177e4SLinus Torvalds * System call vectors. 23481da177e4SLinus Torvalds * 23491da177e4SLinus Torvalds * Argument checking cleaned up. Saved 20% in size. 23501da177e4SLinus Torvalds * This function doesn't need to set the kernel lock because 23511da177e4SLinus Torvalds * it is set by the callees. 23521da177e4SLinus Torvalds */ 23531da177e4SLinus Torvalds 23543e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) 23551da177e4SLinus Torvalds { 23561da177e4SLinus Torvalds unsigned long a[6]; 23571da177e4SLinus Torvalds unsigned long a0, a1; 23581da177e4SLinus Torvalds int err; 235947379052SArjan van de Ven unsigned int len; 23601da177e4SLinus Torvalds 2361228e548eSAnton Blanchard if (call < 1 || call > SYS_SENDMMSG) 23621da177e4SLinus Torvalds return -EINVAL; 23631da177e4SLinus Torvalds 236447379052SArjan van de Ven len = nargs[call]; 236547379052SArjan van de Ven if (len > sizeof(a)) 236647379052SArjan van de Ven return -EINVAL; 236747379052SArjan van de Ven 23681da177e4SLinus Torvalds /* copy_from_user should be SMP safe. */ 236947379052SArjan van de Ven if (copy_from_user(a, args, len)) 23701da177e4SLinus Torvalds return -EFAULT; 23711da177e4SLinus Torvalds 2372f3298dc4SAl Viro audit_socketcall(nargs[call] / sizeof(unsigned long), a); 23733ec3b2fbSDavid Woodhouse 23741da177e4SLinus Torvalds a0 = a[0]; 23751da177e4SLinus Torvalds a1 = a[1]; 23761da177e4SLinus Torvalds 237789bddce5SStephen Hemminger switch (call) { 23781da177e4SLinus Torvalds case SYS_SOCKET: 23791da177e4SLinus Torvalds err = sys_socket(a0, a1, a[2]); 23801da177e4SLinus Torvalds break; 23811da177e4SLinus Torvalds case SYS_BIND: 23821da177e4SLinus Torvalds err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]); 23831da177e4SLinus Torvalds break; 23841da177e4SLinus Torvalds case SYS_CONNECT: 23851da177e4SLinus Torvalds err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]); 23861da177e4SLinus Torvalds break; 23871da177e4SLinus Torvalds case SYS_LISTEN: 23881da177e4SLinus Torvalds err = sys_listen(a0, a1); 23891da177e4SLinus Torvalds break; 23901da177e4SLinus Torvalds case SYS_ACCEPT: 2391de11defeSUlrich Drepper err = sys_accept4(a0, (struct sockaddr __user *)a1, 2392aaca0bdcSUlrich Drepper (int __user *)a[2], 0); 23931da177e4SLinus Torvalds break; 23941da177e4SLinus Torvalds case SYS_GETSOCKNAME: 239589bddce5SStephen Hemminger err = 239689bddce5SStephen Hemminger sys_getsockname(a0, (struct sockaddr __user *)a1, 239789bddce5SStephen Hemminger (int __user *)a[2]); 23981da177e4SLinus Torvalds break; 23991da177e4SLinus Torvalds case SYS_GETPEERNAME: 240089bddce5SStephen Hemminger err = 240189bddce5SStephen Hemminger sys_getpeername(a0, (struct sockaddr __user *)a1, 240289bddce5SStephen Hemminger (int __user *)a[2]); 24031da177e4SLinus Torvalds break; 24041da177e4SLinus Torvalds case SYS_SOCKETPAIR: 24051da177e4SLinus Torvalds err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]); 24061da177e4SLinus Torvalds break; 24071da177e4SLinus Torvalds case SYS_SEND: 24081da177e4SLinus Torvalds err = sys_send(a0, (void __user *)a1, a[2], a[3]); 24091da177e4SLinus Torvalds break; 24101da177e4SLinus Torvalds case SYS_SENDTO: 24111da177e4SLinus Torvalds err = sys_sendto(a0, (void __user *)a1, a[2], a[3], 24121da177e4SLinus Torvalds (struct sockaddr __user *)a[4], a[5]); 24131da177e4SLinus Torvalds break; 24141da177e4SLinus Torvalds case SYS_RECV: 24151da177e4SLinus Torvalds err = sys_recv(a0, (void __user *)a1, a[2], a[3]); 24161da177e4SLinus Torvalds break; 24171da177e4SLinus Torvalds case SYS_RECVFROM: 24181da177e4SLinus Torvalds err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 241989bddce5SStephen Hemminger (struct sockaddr __user *)a[4], 242089bddce5SStephen Hemminger (int __user *)a[5]); 24211da177e4SLinus Torvalds break; 24221da177e4SLinus Torvalds case SYS_SHUTDOWN: 24231da177e4SLinus Torvalds err = sys_shutdown(a0, a1); 24241da177e4SLinus Torvalds break; 24251da177e4SLinus Torvalds case SYS_SETSOCKOPT: 24261da177e4SLinus Torvalds err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]); 24271da177e4SLinus Torvalds break; 24281da177e4SLinus Torvalds case SYS_GETSOCKOPT: 242989bddce5SStephen Hemminger err = 243089bddce5SStephen Hemminger sys_getsockopt(a0, a1, a[2], (char __user *)a[3], 243189bddce5SStephen Hemminger (int __user *)a[4]); 24321da177e4SLinus Torvalds break; 24331da177e4SLinus Torvalds case SYS_SENDMSG: 24341da177e4SLinus Torvalds err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); 24351da177e4SLinus Torvalds break; 2436228e548eSAnton Blanchard case SYS_SENDMMSG: 2437228e548eSAnton Blanchard err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); 2438228e548eSAnton Blanchard break; 24391da177e4SLinus Torvalds case SYS_RECVMSG: 24401da177e4SLinus Torvalds err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); 24411da177e4SLinus Torvalds break; 2442a2e27255SArnaldo Carvalho de Melo case SYS_RECVMMSG: 2443a2e27255SArnaldo Carvalho de Melo err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], 2444a2e27255SArnaldo Carvalho de Melo (struct timespec __user *)a[4]); 2445a2e27255SArnaldo Carvalho de Melo break; 2446de11defeSUlrich Drepper case SYS_ACCEPT4: 2447de11defeSUlrich Drepper err = sys_accept4(a0, (struct sockaddr __user *)a1, 2448de11defeSUlrich Drepper (int __user *)a[2], a[3]); 2449aaca0bdcSUlrich Drepper break; 24501da177e4SLinus Torvalds default: 24511da177e4SLinus Torvalds err = -EINVAL; 24521da177e4SLinus Torvalds break; 24531da177e4SLinus Torvalds } 24541da177e4SLinus Torvalds return err; 24551da177e4SLinus Torvalds } 24561da177e4SLinus Torvalds 24571da177e4SLinus Torvalds #endif /* __ARCH_WANT_SYS_SOCKETCALL */ 24581da177e4SLinus Torvalds 245955737fdaSStephen Hemminger /** 246055737fdaSStephen Hemminger * sock_register - add a socket protocol handler 246155737fdaSStephen Hemminger * @ops: description of protocol 246255737fdaSStephen Hemminger * 24631da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 24641da177e4SLinus Torvalds * advertise its address family, and have it linked into the 246555737fdaSStephen Hemminger * socket interface. The value ops->family coresponds to the 246655737fdaSStephen Hemminger * socket system call protocol family. 24671da177e4SLinus Torvalds */ 2468f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops) 24691da177e4SLinus Torvalds { 24701da177e4SLinus Torvalds int err; 24711da177e4SLinus Torvalds 24721da177e4SLinus Torvalds if (ops->family >= NPROTO) { 247389bddce5SStephen Hemminger printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family, 247489bddce5SStephen Hemminger NPROTO); 24751da177e4SLinus Torvalds return -ENOBUFS; 24761da177e4SLinus Torvalds } 247755737fdaSStephen Hemminger 247855737fdaSStephen Hemminger spin_lock(&net_family_lock); 2479190683a9SEric Dumazet if (rcu_dereference_protected(net_families[ops->family], 2480190683a9SEric Dumazet lockdep_is_held(&net_family_lock))) 24811da177e4SLinus Torvalds err = -EEXIST; 248255737fdaSStephen Hemminger else { 2483cf778b00SEric Dumazet rcu_assign_pointer(net_families[ops->family], ops); 24841da177e4SLinus Torvalds err = 0; 24851da177e4SLinus Torvalds } 248655737fdaSStephen Hemminger spin_unlock(&net_family_lock); 248755737fdaSStephen Hemminger 248889bddce5SStephen Hemminger printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family); 24891da177e4SLinus Torvalds return err; 24901da177e4SLinus Torvalds } 2491c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register); 24921da177e4SLinus Torvalds 249355737fdaSStephen Hemminger /** 249455737fdaSStephen Hemminger * sock_unregister - remove a protocol handler 249555737fdaSStephen Hemminger * @family: protocol family to remove 249655737fdaSStephen Hemminger * 24971da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 24981da177e4SLinus Torvalds * remove its address family, and have it unlinked from the 249955737fdaSStephen Hemminger * new socket creation. 250055737fdaSStephen Hemminger * 250155737fdaSStephen Hemminger * If protocol handler is a module, then it can use module reference 250255737fdaSStephen Hemminger * counts to protect against new references. If protocol handler is not 250355737fdaSStephen Hemminger * a module then it needs to provide its own protection in 250455737fdaSStephen Hemminger * the ops->create routine. 25051da177e4SLinus Torvalds */ 2506f0fd27d4SStephen Hemminger void sock_unregister(int family) 25071da177e4SLinus Torvalds { 2508f0fd27d4SStephen Hemminger BUG_ON(family < 0 || family >= NPROTO); 25091da177e4SLinus Torvalds 251055737fdaSStephen Hemminger spin_lock(&net_family_lock); 2511a9b3cd7fSStephen Hemminger RCU_INIT_POINTER(net_families[family], NULL); 251255737fdaSStephen Hemminger spin_unlock(&net_family_lock); 251355737fdaSStephen Hemminger 251455737fdaSStephen Hemminger synchronize_rcu(); 251555737fdaSStephen Hemminger 251689bddce5SStephen Hemminger printk(KERN_INFO "NET: Unregistered protocol family %d\n", family); 25171da177e4SLinus Torvalds } 2518c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister); 25191da177e4SLinus Torvalds 252077d76ea3SAndi Kleen static int __init sock_init(void) 25211da177e4SLinus Torvalds { 2522b3e19d92SNick Piggin int err; 25232ca794e5SEric W. Biederman /* 25242ca794e5SEric W. Biederman * Initialize the network sysctl infrastructure. 25252ca794e5SEric W. Biederman */ 25262ca794e5SEric W. Biederman err = net_sysctl_init(); 25272ca794e5SEric W. Biederman if (err) 25282ca794e5SEric W. Biederman goto out; 2529b3e19d92SNick Piggin 25301da177e4SLinus Torvalds /* 25311da177e4SLinus Torvalds * Initialize sock SLAB cache. 25321da177e4SLinus Torvalds */ 25331da177e4SLinus Torvalds 25341da177e4SLinus Torvalds sk_init(); 25351da177e4SLinus Torvalds 25361da177e4SLinus Torvalds /* 25371da177e4SLinus Torvalds * Initialize skbuff SLAB cache 25381da177e4SLinus Torvalds */ 25391da177e4SLinus Torvalds skb_init(); 25401da177e4SLinus Torvalds 25411da177e4SLinus Torvalds /* 25421da177e4SLinus Torvalds * Initialize the protocols module. 25431da177e4SLinus Torvalds */ 25441da177e4SLinus Torvalds 25451da177e4SLinus Torvalds init_inodecache(); 2546b3e19d92SNick Piggin 2547b3e19d92SNick Piggin err = register_filesystem(&sock_fs_type); 2548b3e19d92SNick Piggin if (err) 2549b3e19d92SNick Piggin goto out_fs; 25501da177e4SLinus Torvalds sock_mnt = kern_mount(&sock_fs_type); 2551b3e19d92SNick Piggin if (IS_ERR(sock_mnt)) { 2552b3e19d92SNick Piggin err = PTR_ERR(sock_mnt); 2553b3e19d92SNick Piggin goto out_mount; 2554b3e19d92SNick Piggin } 255577d76ea3SAndi Kleen 255677d76ea3SAndi Kleen /* The real protocol initialization is performed in later initcalls. 25571da177e4SLinus Torvalds */ 25581da177e4SLinus Torvalds 25591da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER 25601da177e4SLinus Torvalds netfilter_init(); 25611da177e4SLinus Torvalds #endif 2562cbeb321aSDavid S. Miller 2563c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING 2564c1f19b51SRichard Cochran skb_timestamping_init(); 2565c1f19b51SRichard Cochran #endif 2566c1f19b51SRichard Cochran 2567b3e19d92SNick Piggin out: 2568b3e19d92SNick Piggin return err; 2569b3e19d92SNick Piggin 2570b3e19d92SNick Piggin out_mount: 2571b3e19d92SNick Piggin unregister_filesystem(&sock_fs_type); 2572b3e19d92SNick Piggin out_fs: 2573b3e19d92SNick Piggin goto out; 25741da177e4SLinus Torvalds } 25751da177e4SLinus Torvalds 257677d76ea3SAndi Kleen core_initcall(sock_init); /* early initcall */ 257777d76ea3SAndi Kleen 25781da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 25791da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq) 25801da177e4SLinus Torvalds { 25811da177e4SLinus Torvalds int cpu; 25821da177e4SLinus Torvalds int counter = 0; 25831da177e4SLinus Torvalds 25846f912042SKAMEZAWA Hiroyuki for_each_possible_cpu(cpu) 25851da177e4SLinus Torvalds counter += per_cpu(sockets_in_use, cpu); 25861da177e4SLinus Torvalds 25871da177e4SLinus Torvalds /* It can be negative, by the way. 8) */ 25881da177e4SLinus Torvalds if (counter < 0) 25891da177e4SLinus Torvalds counter = 0; 25901da177e4SLinus Torvalds 25911da177e4SLinus Torvalds seq_printf(seq, "sockets: used %d\n", counter); 25921da177e4SLinus Torvalds } 25931da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */ 25941da177e4SLinus Torvalds 259589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 25966b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock, 2597644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 25987a229387SArnd Bergmann { 25997a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 26007a229387SArnd Bergmann struct timeval ktv; 26017a229387SArnd Bergmann int err; 26027a229387SArnd Bergmann 26037a229387SArnd Bergmann set_fs(KERNEL_DS); 26046b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); 26057a229387SArnd Bergmann set_fs(old_fs); 2606644595f8SH. Peter Anvin if (!err) 2607ed6fe9d6SMikulas Patocka err = compat_put_timeval(&ktv, up); 2608644595f8SH. Peter Anvin 26097a229387SArnd Bergmann return err; 26107a229387SArnd Bergmann } 26117a229387SArnd Bergmann 26126b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock, 2613644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 26147a229387SArnd Bergmann { 26157a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 26167a229387SArnd Bergmann struct timespec kts; 26177a229387SArnd Bergmann int err; 26187a229387SArnd Bergmann 26197a229387SArnd Bergmann set_fs(KERNEL_DS); 26206b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); 26217a229387SArnd Bergmann set_fs(old_fs); 2622644595f8SH. Peter Anvin if (!err) 2623ed6fe9d6SMikulas Patocka err = compat_put_timespec(&kts, up); 2624644595f8SH. Peter Anvin 26257a229387SArnd Bergmann return err; 26267a229387SArnd Bergmann } 26277a229387SArnd Bergmann 26286b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32) 26297a229387SArnd Bergmann { 26307a229387SArnd Bergmann struct ifreq __user *uifr; 26317a229387SArnd Bergmann int err; 26327a229387SArnd Bergmann 26337a229387SArnd Bergmann uifr = compat_alloc_user_space(sizeof(struct ifreq)); 26346b96018bSArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 26357a229387SArnd Bergmann return -EFAULT; 26367a229387SArnd Bergmann 26376b96018bSArnd Bergmann err = dev_ioctl(net, SIOCGIFNAME, uifr); 26387a229387SArnd Bergmann if (err) 26397a229387SArnd Bergmann return err; 26407a229387SArnd Bergmann 26416b96018bSArnd Bergmann if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq))) 26427a229387SArnd Bergmann return -EFAULT; 26437a229387SArnd Bergmann 26447a229387SArnd Bergmann return 0; 26457a229387SArnd Bergmann } 26467a229387SArnd Bergmann 26476b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) 26487a229387SArnd Bergmann { 26496b96018bSArnd Bergmann struct compat_ifconf ifc32; 26507a229387SArnd Bergmann struct ifconf ifc; 26517a229387SArnd Bergmann struct ifconf __user *uifc; 26526b96018bSArnd Bergmann struct compat_ifreq __user *ifr32; 26537a229387SArnd Bergmann struct ifreq __user *ifr; 26547a229387SArnd Bergmann unsigned int i, j; 26557a229387SArnd Bergmann int err; 26567a229387SArnd Bergmann 26576b96018bSArnd Bergmann if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) 26587a229387SArnd Bergmann return -EFAULT; 26597a229387SArnd Bergmann 266043da5f2eSMathias Krause memset(&ifc, 0, sizeof(ifc)); 26617a229387SArnd Bergmann if (ifc32.ifcbuf == 0) { 26627a229387SArnd Bergmann ifc32.ifc_len = 0; 26637a229387SArnd Bergmann ifc.ifc_len = 0; 26647a229387SArnd Bergmann ifc.ifc_req = NULL; 26657a229387SArnd Bergmann uifc = compat_alloc_user_space(sizeof(struct ifconf)); 26667a229387SArnd Bergmann } else { 26676b96018bSArnd Bergmann size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) * 26687a229387SArnd Bergmann sizeof(struct ifreq); 26697a229387SArnd Bergmann uifc = compat_alloc_user_space(sizeof(struct ifconf) + len); 26707a229387SArnd Bergmann ifc.ifc_len = len; 26717a229387SArnd Bergmann ifr = ifc.ifc_req = (void __user *)(uifc + 1); 26727a229387SArnd Bergmann ifr32 = compat_ptr(ifc32.ifcbuf); 26736b96018bSArnd Bergmann for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) { 26746b96018bSArnd Bergmann if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq))) 26757a229387SArnd Bergmann return -EFAULT; 26767a229387SArnd Bergmann ifr++; 26777a229387SArnd Bergmann ifr32++; 26787a229387SArnd Bergmann } 26797a229387SArnd Bergmann } 26807a229387SArnd Bergmann if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) 26817a229387SArnd Bergmann return -EFAULT; 26827a229387SArnd Bergmann 26836b96018bSArnd Bergmann err = dev_ioctl(net, SIOCGIFCONF, uifc); 26847a229387SArnd Bergmann if (err) 26857a229387SArnd Bergmann return err; 26867a229387SArnd Bergmann 26877a229387SArnd Bergmann if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) 26887a229387SArnd Bergmann return -EFAULT; 26897a229387SArnd Bergmann 26907a229387SArnd Bergmann ifr = ifc.ifc_req; 26917a229387SArnd Bergmann ifr32 = compat_ptr(ifc32.ifcbuf); 26927a229387SArnd Bergmann for (i = 0, j = 0; 26936b96018bSArnd Bergmann i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len; 26946b96018bSArnd Bergmann i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) { 26956b96018bSArnd Bergmann if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq))) 26967a229387SArnd Bergmann return -EFAULT; 26977a229387SArnd Bergmann ifr32++; 26987a229387SArnd Bergmann ifr++; 26997a229387SArnd Bergmann } 27007a229387SArnd Bergmann 27017a229387SArnd Bergmann if (ifc32.ifcbuf == 0) { 27027a229387SArnd Bergmann /* Translate from 64-bit structure multiple to 27037a229387SArnd Bergmann * a 32-bit one. 27047a229387SArnd Bergmann */ 27057a229387SArnd Bergmann i = ifc.ifc_len; 27066b96018bSArnd Bergmann i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq)); 27077a229387SArnd Bergmann ifc32.ifc_len = i; 27087a229387SArnd Bergmann } else { 27097a229387SArnd Bergmann ifc32.ifc_len = i; 27107a229387SArnd Bergmann } 27116b96018bSArnd Bergmann if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) 27127a229387SArnd Bergmann return -EFAULT; 27137a229387SArnd Bergmann 27147a229387SArnd Bergmann return 0; 27157a229387SArnd Bergmann } 27167a229387SArnd Bergmann 27176b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) 27187a229387SArnd Bergmann { 27193a7da39dSBen Hutchings struct compat_ethtool_rxnfc __user *compat_rxnfc; 27203a7da39dSBen Hutchings bool convert_in = false, convert_out = false; 27213a7da39dSBen Hutchings size_t buf_size = ALIGN(sizeof(struct ifreq), 8); 27223a7da39dSBen Hutchings struct ethtool_rxnfc __user *rxnfc; 27237a229387SArnd Bergmann struct ifreq __user *ifr; 27243a7da39dSBen Hutchings u32 rule_cnt = 0, actual_rule_cnt; 27253a7da39dSBen Hutchings u32 ethcmd; 27267a229387SArnd Bergmann u32 data; 27273a7da39dSBen Hutchings int ret; 27287a229387SArnd Bergmann 27297a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 27307a229387SArnd Bergmann return -EFAULT; 27317a229387SArnd Bergmann 27323a7da39dSBen Hutchings compat_rxnfc = compat_ptr(data); 27333a7da39dSBen Hutchings 27343a7da39dSBen Hutchings if (get_user(ethcmd, &compat_rxnfc->cmd)) 27357a229387SArnd Bergmann return -EFAULT; 27367a229387SArnd Bergmann 27373a7da39dSBen Hutchings /* Most ethtool structures are defined without padding. 27383a7da39dSBen Hutchings * Unfortunately struct ethtool_rxnfc is an exception. 27393a7da39dSBen Hutchings */ 27403a7da39dSBen Hutchings switch (ethcmd) { 27413a7da39dSBen Hutchings default: 27423a7da39dSBen Hutchings break; 27433a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLALL: 27443a7da39dSBen Hutchings /* Buffer size is variable */ 27453a7da39dSBen Hutchings if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) 27463a7da39dSBen Hutchings return -EFAULT; 27473a7da39dSBen Hutchings if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) 27483a7da39dSBen Hutchings return -ENOMEM; 27493a7da39dSBen Hutchings buf_size += rule_cnt * sizeof(u32); 27503a7da39dSBen Hutchings /* fall through */ 27513a7da39dSBen Hutchings case ETHTOOL_GRXRINGS: 27523a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLCNT: 27533a7da39dSBen Hutchings case ETHTOOL_GRXCLSRULE: 275455664f32SBen Hutchings case ETHTOOL_SRXCLSRLINS: 27553a7da39dSBen Hutchings convert_out = true; 27563a7da39dSBen Hutchings /* fall through */ 27573a7da39dSBen Hutchings case ETHTOOL_SRXCLSRLDEL: 27583a7da39dSBen Hutchings buf_size += sizeof(struct ethtool_rxnfc); 27593a7da39dSBen Hutchings convert_in = true; 27603a7da39dSBen Hutchings break; 27613a7da39dSBen Hutchings } 27623a7da39dSBen Hutchings 27633a7da39dSBen Hutchings ifr = compat_alloc_user_space(buf_size); 27643a7da39dSBen Hutchings rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8); 27653a7da39dSBen Hutchings 27663a7da39dSBen Hutchings if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 27673a7da39dSBen Hutchings return -EFAULT; 27683a7da39dSBen Hutchings 27693a7da39dSBen Hutchings if (put_user(convert_in ? rxnfc : compat_ptr(data), 27703a7da39dSBen Hutchings &ifr->ifr_ifru.ifru_data)) 27713a7da39dSBen Hutchings return -EFAULT; 27723a7da39dSBen Hutchings 27733a7da39dSBen Hutchings if (convert_in) { 2774127fe533SAlexander Duyck /* We expect there to be holes between fs.m_ext and 27753a7da39dSBen Hutchings * fs.ring_cookie and at the end of fs, but nowhere else. 27763a7da39dSBen Hutchings */ 2777127fe533SAlexander Duyck BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + 2778127fe533SAlexander Duyck sizeof(compat_rxnfc->fs.m_ext) != 2779127fe533SAlexander Duyck offsetof(struct ethtool_rxnfc, fs.m_ext) + 2780127fe533SAlexander Duyck sizeof(rxnfc->fs.m_ext)); 27813a7da39dSBen Hutchings BUILD_BUG_ON( 27823a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.location) - 27833a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != 27843a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.location) - 27853a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.ring_cookie)); 27863a7da39dSBen Hutchings 27873a7da39dSBen Hutchings if (copy_in_user(rxnfc, compat_rxnfc, 2788127fe533SAlexander Duyck (void *)(&rxnfc->fs.m_ext + 1) - 27893a7da39dSBen Hutchings (void *)rxnfc) || 27903a7da39dSBen Hutchings copy_in_user(&rxnfc->fs.ring_cookie, 27913a7da39dSBen Hutchings &compat_rxnfc->fs.ring_cookie, 27923a7da39dSBen Hutchings (void *)(&rxnfc->fs.location + 1) - 27933a7da39dSBen Hutchings (void *)&rxnfc->fs.ring_cookie) || 27943a7da39dSBen Hutchings copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt, 27953a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 27963a7da39dSBen Hutchings return -EFAULT; 27973a7da39dSBen Hutchings } 27983a7da39dSBen Hutchings 27993a7da39dSBen Hutchings ret = dev_ioctl(net, SIOCETHTOOL, ifr); 28003a7da39dSBen Hutchings if (ret) 28013a7da39dSBen Hutchings return ret; 28023a7da39dSBen Hutchings 28033a7da39dSBen Hutchings if (convert_out) { 28043a7da39dSBen Hutchings if (copy_in_user(compat_rxnfc, rxnfc, 2805127fe533SAlexander Duyck (const void *)(&rxnfc->fs.m_ext + 1) - 28063a7da39dSBen Hutchings (const void *)rxnfc) || 28073a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->fs.ring_cookie, 28083a7da39dSBen Hutchings &rxnfc->fs.ring_cookie, 28093a7da39dSBen Hutchings (const void *)(&rxnfc->fs.location + 1) - 28103a7da39dSBen Hutchings (const void *)&rxnfc->fs.ring_cookie) || 28113a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, 28123a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 28133a7da39dSBen Hutchings return -EFAULT; 28143a7da39dSBen Hutchings 28153a7da39dSBen Hutchings if (ethcmd == ETHTOOL_GRXCLSRLALL) { 28163a7da39dSBen Hutchings /* As an optimisation, we only copy the actual 28173a7da39dSBen Hutchings * number of rules that the underlying 28183a7da39dSBen Hutchings * function returned. Since Mallory might 28193a7da39dSBen Hutchings * change the rule count in user memory, we 28203a7da39dSBen Hutchings * check that it is less than the rule count 28213a7da39dSBen Hutchings * originally given (as the user buffer size), 28223a7da39dSBen Hutchings * which has been range-checked. 28233a7da39dSBen Hutchings */ 28243a7da39dSBen Hutchings if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) 28253a7da39dSBen Hutchings return -EFAULT; 28263a7da39dSBen Hutchings if (actual_rule_cnt < rule_cnt) 28273a7da39dSBen Hutchings rule_cnt = actual_rule_cnt; 28283a7da39dSBen Hutchings if (copy_in_user(&compat_rxnfc->rule_locs[0], 28293a7da39dSBen Hutchings &rxnfc->rule_locs[0], 28303a7da39dSBen Hutchings rule_cnt * sizeof(u32))) 28313a7da39dSBen Hutchings return -EFAULT; 28323a7da39dSBen Hutchings } 28333a7da39dSBen Hutchings } 28343a7da39dSBen Hutchings 28353a7da39dSBen Hutchings return 0; 28367a229387SArnd Bergmann } 28377a229387SArnd Bergmann 28387a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) 28397a50a240SArnd Bergmann { 28407a50a240SArnd Bergmann void __user *uptr; 28417a50a240SArnd Bergmann compat_uptr_t uptr32; 28427a50a240SArnd Bergmann struct ifreq __user *uifr; 28437a50a240SArnd Bergmann 28447a50a240SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 28457a50a240SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 28467a50a240SArnd Bergmann return -EFAULT; 28477a50a240SArnd Bergmann 28487a50a240SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) 28497a50a240SArnd Bergmann return -EFAULT; 28507a50a240SArnd Bergmann 28517a50a240SArnd Bergmann uptr = compat_ptr(uptr32); 28527a50a240SArnd Bergmann 28537a50a240SArnd Bergmann if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc)) 28547a50a240SArnd Bergmann return -EFAULT; 28557a50a240SArnd Bergmann 28567a50a240SArnd Bergmann return dev_ioctl(net, SIOCWANDEV, uifr); 28577a50a240SArnd Bergmann } 28587a50a240SArnd Bergmann 28596b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd, 28606b96018bSArnd Bergmann struct compat_ifreq __user *ifr32) 28617a229387SArnd Bergmann { 28627a229387SArnd Bergmann struct ifreq kifr; 28637a229387SArnd Bergmann struct ifreq __user *uifr; 28647a229387SArnd Bergmann mm_segment_t old_fs; 28657a229387SArnd Bergmann int err; 28667a229387SArnd Bergmann u32 data; 28677a229387SArnd Bergmann void __user *datap; 28687a229387SArnd Bergmann 28697a229387SArnd Bergmann switch (cmd) { 28707a229387SArnd Bergmann case SIOCBONDENSLAVE: 28717a229387SArnd Bergmann case SIOCBONDRELEASE: 28727a229387SArnd Bergmann case SIOCBONDSETHWADDR: 28737a229387SArnd Bergmann case SIOCBONDCHANGEACTIVE: 28746b96018bSArnd Bergmann if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq))) 28757a229387SArnd Bergmann return -EFAULT; 28767a229387SArnd Bergmann 28777a229387SArnd Bergmann old_fs = get_fs(); 28787a229387SArnd Bergmann set_fs(KERNEL_DS); 2879c3f52ae6Sstephen hemminger err = dev_ioctl(net, cmd, 2880c3f52ae6Sstephen hemminger (struct ifreq __user __force *) &kifr); 28817a229387SArnd Bergmann set_fs(old_fs); 28827a229387SArnd Bergmann 28837a229387SArnd Bergmann return err; 28847a229387SArnd Bergmann case SIOCBONDSLAVEINFOQUERY: 28857a229387SArnd Bergmann case SIOCBONDINFOQUERY: 28867a229387SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 28877a229387SArnd Bergmann if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 28887a229387SArnd Bergmann return -EFAULT; 28897a229387SArnd Bergmann 28907a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 28917a229387SArnd Bergmann return -EFAULT; 28927a229387SArnd Bergmann 28937a229387SArnd Bergmann datap = compat_ptr(data); 28947a229387SArnd Bergmann if (put_user(datap, &uifr->ifr_ifru.ifru_data)) 28957a229387SArnd Bergmann return -EFAULT; 28967a229387SArnd Bergmann 28976b96018bSArnd Bergmann return dev_ioctl(net, cmd, uifr); 28987a229387SArnd Bergmann default: 289907d106d0SLinus Torvalds return -ENOIOCTLCMD; 2900ccbd6a5aSJoe Perches } 29017a229387SArnd Bergmann } 29027a229387SArnd Bergmann 29036b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, 29046b96018bSArnd Bergmann struct compat_ifreq __user *u_ifreq32) 29057a229387SArnd Bergmann { 29067a229387SArnd Bergmann struct ifreq __user *u_ifreq64; 29077a229387SArnd Bergmann char tmp_buf[IFNAMSIZ]; 29087a229387SArnd Bergmann void __user *data64; 29097a229387SArnd Bergmann u32 data32; 29107a229387SArnd Bergmann 29117a229387SArnd Bergmann if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), 29127a229387SArnd Bergmann IFNAMSIZ)) 29137a229387SArnd Bergmann return -EFAULT; 29147a229387SArnd Bergmann if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) 29157a229387SArnd Bergmann return -EFAULT; 29167a229387SArnd Bergmann data64 = compat_ptr(data32); 29177a229387SArnd Bergmann 29187a229387SArnd Bergmann u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); 29197a229387SArnd Bergmann 29207a229387SArnd Bergmann /* Don't check these user accesses, just let that get trapped 29217a229387SArnd Bergmann * in the ioctl handler instead. 29227a229387SArnd Bergmann */ 29237a229387SArnd Bergmann if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], 29247a229387SArnd Bergmann IFNAMSIZ)) 29257a229387SArnd Bergmann return -EFAULT; 29267a229387SArnd Bergmann if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) 29277a229387SArnd Bergmann return -EFAULT; 29287a229387SArnd Bergmann 29296b96018bSArnd Bergmann return dev_ioctl(net, cmd, u_ifreq64); 29307a229387SArnd Bergmann } 29317a229387SArnd Bergmann 29326b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock, 29336b96018bSArnd Bergmann unsigned int cmd, struct compat_ifreq __user *uifr32) 29347a229387SArnd Bergmann { 2935a2116ed2SArnd Bergmann struct ifreq __user *uifr; 29367a229387SArnd Bergmann int err; 29377a229387SArnd Bergmann 2938a2116ed2SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 2939a2116ed2SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(*uifr32))) 29407a229387SArnd Bergmann return -EFAULT; 2941a2116ed2SArnd Bergmann 2942a2116ed2SArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr); 2943a2116ed2SArnd Bergmann 29447a229387SArnd Bergmann if (!err) { 29457a229387SArnd Bergmann switch (cmd) { 29467a229387SArnd Bergmann case SIOCGIFFLAGS: 29477a229387SArnd Bergmann case SIOCGIFMETRIC: 29487a229387SArnd Bergmann case SIOCGIFMTU: 29497a229387SArnd Bergmann case SIOCGIFMEM: 29507a229387SArnd Bergmann case SIOCGIFHWADDR: 29517a229387SArnd Bergmann case SIOCGIFINDEX: 29527a229387SArnd Bergmann case SIOCGIFADDR: 29537a229387SArnd Bergmann case SIOCGIFBRDADDR: 29547a229387SArnd Bergmann case SIOCGIFDSTADDR: 29557a229387SArnd Bergmann case SIOCGIFNETMASK: 2956fab2532bSArnd Bergmann case SIOCGIFPFLAGS: 29577a229387SArnd Bergmann case SIOCGIFTXQLEN: 2958fab2532bSArnd Bergmann case SIOCGMIIPHY: 2959fab2532bSArnd Bergmann case SIOCGMIIREG: 2960a2116ed2SArnd Bergmann if (copy_in_user(uifr32, uifr, sizeof(*uifr32))) 2961a2116ed2SArnd Bergmann err = -EFAULT; 29627a229387SArnd Bergmann break; 2963a2116ed2SArnd Bergmann } 2964a2116ed2SArnd Bergmann } 2965a2116ed2SArnd Bergmann return err; 2966a2116ed2SArnd Bergmann } 2967a2116ed2SArnd Bergmann 2968a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 2969a2116ed2SArnd Bergmann struct compat_ifreq __user *uifr32) 2970a2116ed2SArnd Bergmann { 2971a2116ed2SArnd Bergmann struct ifreq ifr; 2972a2116ed2SArnd Bergmann struct compat_ifmap __user *uifmap32; 2973a2116ed2SArnd Bergmann mm_segment_t old_fs; 2974a2116ed2SArnd Bergmann int err; 2975a2116ed2SArnd Bergmann 2976a2116ed2SArnd Bergmann uifmap32 = &uifr32->ifr_ifru.ifru_map; 2977a2116ed2SArnd Bergmann err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); 2978a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 2979a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 2980a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 2981a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq); 2982a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma); 2983a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.port, &uifmap32->port); 2984a2116ed2SArnd Bergmann if (err) 2985a2116ed2SArnd Bergmann return -EFAULT; 2986a2116ed2SArnd Bergmann 2987a2116ed2SArnd Bergmann old_fs = get_fs(); 2988a2116ed2SArnd Bergmann set_fs(KERNEL_DS); 2989c3f52ae6Sstephen hemminger err = dev_ioctl(net, cmd, (void __user __force *)&ifr); 2990a2116ed2SArnd Bergmann set_fs(old_fs); 2991a2116ed2SArnd Bergmann 2992a2116ed2SArnd Bergmann if (cmd == SIOCGIFMAP && !err) { 29937a229387SArnd Bergmann err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); 29947a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 29957a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 29967a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 29977a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq); 29987a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma); 29997a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.port, &uifmap32->port); 30007a229387SArnd Bergmann if (err) 30017a229387SArnd Bergmann err = -EFAULT; 30027a229387SArnd Bergmann } 30037a229387SArnd Bergmann return err; 30047a229387SArnd Bergmann } 30057a229387SArnd Bergmann 3006a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32) 3007a2116ed2SArnd Bergmann { 3008a2116ed2SArnd Bergmann void __user *uptr; 3009a2116ed2SArnd Bergmann compat_uptr_t uptr32; 3010a2116ed2SArnd Bergmann struct ifreq __user *uifr; 3011a2116ed2SArnd Bergmann 3012a2116ed2SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 3013a2116ed2SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 3014a2116ed2SArnd Bergmann return -EFAULT; 3015a2116ed2SArnd Bergmann 3016a2116ed2SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_data)) 3017a2116ed2SArnd Bergmann return -EFAULT; 3018a2116ed2SArnd Bergmann 3019a2116ed2SArnd Bergmann uptr = compat_ptr(uptr32); 3020a2116ed2SArnd Bergmann 3021a2116ed2SArnd Bergmann if (put_user(uptr, &uifr->ifr_data)) 3022a2116ed2SArnd Bergmann return -EFAULT; 3023a2116ed2SArnd Bergmann 3024a2116ed2SArnd Bergmann return dev_ioctl(net, SIOCSHWTSTAMP, uifr); 3025a2116ed2SArnd Bergmann } 3026a2116ed2SArnd Bergmann 30277a229387SArnd Bergmann struct rtentry32 { 30287a229387SArnd Bergmann u32 rt_pad1; 30297a229387SArnd Bergmann struct sockaddr rt_dst; /* target address */ 30307a229387SArnd Bergmann struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ 30317a229387SArnd Bergmann struct sockaddr rt_genmask; /* target network mask (IP) */ 30327a229387SArnd Bergmann unsigned short rt_flags; 30337a229387SArnd Bergmann short rt_pad2; 30347a229387SArnd Bergmann u32 rt_pad3; 30357a229387SArnd Bergmann unsigned char rt_tos; 30367a229387SArnd Bergmann unsigned char rt_class; 30377a229387SArnd Bergmann short rt_pad4; 30387a229387SArnd Bergmann short rt_metric; /* +1 for binary compatibility! */ 30397a229387SArnd Bergmann /* char * */ u32 rt_dev; /* forcing the device at add */ 30407a229387SArnd Bergmann u32 rt_mtu; /* per route MTU/Window */ 30417a229387SArnd Bergmann u32 rt_window; /* Window clamping */ 30427a229387SArnd Bergmann unsigned short rt_irtt; /* Initial RTT */ 30437a229387SArnd Bergmann }; 30447a229387SArnd Bergmann 30457a229387SArnd Bergmann struct in6_rtmsg32 { 30467a229387SArnd Bergmann struct in6_addr rtmsg_dst; 30477a229387SArnd Bergmann struct in6_addr rtmsg_src; 30487a229387SArnd Bergmann struct in6_addr rtmsg_gateway; 30497a229387SArnd Bergmann u32 rtmsg_type; 30507a229387SArnd Bergmann u16 rtmsg_dst_len; 30517a229387SArnd Bergmann u16 rtmsg_src_len; 30527a229387SArnd Bergmann u32 rtmsg_metric; 30537a229387SArnd Bergmann u32 rtmsg_info; 30547a229387SArnd Bergmann u32 rtmsg_flags; 30557a229387SArnd Bergmann s32 rtmsg_ifindex; 30567a229387SArnd Bergmann }; 30577a229387SArnd Bergmann 30586b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock, 30596b96018bSArnd Bergmann unsigned int cmd, void __user *argp) 30607a229387SArnd Bergmann { 30617a229387SArnd Bergmann int ret; 30627a229387SArnd Bergmann void *r = NULL; 30637a229387SArnd Bergmann struct in6_rtmsg r6; 30647a229387SArnd Bergmann struct rtentry r4; 30657a229387SArnd Bergmann char devname[16]; 30667a229387SArnd Bergmann u32 rtdev; 30677a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 30687a229387SArnd Bergmann 30696b96018bSArnd Bergmann if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */ 30706b96018bSArnd Bergmann struct in6_rtmsg32 __user *ur6 = argp; 30717a229387SArnd Bergmann ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst), 30727a229387SArnd Bergmann 3 * sizeof(struct in6_addr)); 30737a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type)); 30747a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); 30757a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); 30767a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric)); 30777a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info)); 30787a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags)); 30797a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); 30807a229387SArnd Bergmann 30817a229387SArnd Bergmann r = (void *) &r6; 30827a229387SArnd Bergmann } else { /* ipv4 */ 30836b96018bSArnd Bergmann struct rtentry32 __user *ur4 = argp; 30847a229387SArnd Bergmann ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst), 30857a229387SArnd Bergmann 3 * sizeof(struct sockaddr)); 30867a229387SArnd Bergmann ret |= __get_user(r4.rt_flags, &(ur4->rt_flags)); 30877a229387SArnd Bergmann ret |= __get_user(r4.rt_metric, &(ur4->rt_metric)); 30887a229387SArnd Bergmann ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu)); 30897a229387SArnd Bergmann ret |= __get_user(r4.rt_window, &(ur4->rt_window)); 30907a229387SArnd Bergmann ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt)); 30917a229387SArnd Bergmann ret |= __get_user(rtdev, &(ur4->rt_dev)); 30927a229387SArnd Bergmann if (rtdev) { 30937a229387SArnd Bergmann ret |= copy_from_user(devname, compat_ptr(rtdev), 15); 3094c3f52ae6Sstephen hemminger r4.rt_dev = (char __user __force *)devname; 3095c3f52ae6Sstephen hemminger devname[15] = 0; 30967a229387SArnd Bergmann } else 30977a229387SArnd Bergmann r4.rt_dev = NULL; 30987a229387SArnd Bergmann 30997a229387SArnd Bergmann r = (void *) &r4; 31007a229387SArnd Bergmann } 31017a229387SArnd Bergmann 31027a229387SArnd Bergmann if (ret) { 31037a229387SArnd Bergmann ret = -EFAULT; 31047a229387SArnd Bergmann goto out; 31057a229387SArnd Bergmann } 31067a229387SArnd Bergmann 31077a229387SArnd Bergmann set_fs(KERNEL_DS); 31086b96018bSArnd Bergmann ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); 31097a229387SArnd Bergmann set_fs(old_fs); 31107a229387SArnd Bergmann 31117a229387SArnd Bergmann out: 31127a229387SArnd Bergmann return ret; 31137a229387SArnd Bergmann } 31147a229387SArnd Bergmann 31157a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE 31167a229387SArnd Bergmann * for some operations; this forces use of the newer bridge-utils that 311725985edcSLucas De Marchi * use compatible ioctls 31187a229387SArnd Bergmann */ 31196b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp) 31207a229387SArnd Bergmann { 31216b96018bSArnd Bergmann compat_ulong_t tmp; 31227a229387SArnd Bergmann 31236b96018bSArnd Bergmann if (get_user(tmp, argp)) 31247a229387SArnd Bergmann return -EFAULT; 31257a229387SArnd Bergmann if (tmp == BRCTL_GET_VERSION) 31267a229387SArnd Bergmann return BRCTL_VERSION + 1; 31277a229387SArnd Bergmann return -EINVAL; 31287a229387SArnd Bergmann } 31297a229387SArnd Bergmann 31306b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, 31316b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 31326b96018bSArnd Bergmann { 31336b96018bSArnd Bergmann void __user *argp = compat_ptr(arg); 31346b96018bSArnd Bergmann struct sock *sk = sock->sk; 31356b96018bSArnd Bergmann struct net *net = sock_net(sk); 31367a229387SArnd Bergmann 31376b96018bSArnd Bergmann if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 31386b96018bSArnd Bergmann return siocdevprivate_ioctl(net, cmd, argp); 31397a229387SArnd Bergmann 31406b96018bSArnd Bergmann switch (cmd) { 31416b96018bSArnd Bergmann case SIOCSIFBR: 31426b96018bSArnd Bergmann case SIOCGIFBR: 31436b96018bSArnd Bergmann return old_bridge_ioctl(argp); 31446b96018bSArnd Bergmann case SIOCGIFNAME: 31456b96018bSArnd Bergmann return dev_ifname32(net, argp); 31466b96018bSArnd Bergmann case SIOCGIFCONF: 31476b96018bSArnd Bergmann return dev_ifconf(net, argp); 31486b96018bSArnd Bergmann case SIOCETHTOOL: 31496b96018bSArnd Bergmann return ethtool_ioctl(net, argp); 31507a50a240SArnd Bergmann case SIOCWANDEV: 31517a50a240SArnd Bergmann return compat_siocwandev(net, argp); 3152a2116ed2SArnd Bergmann case SIOCGIFMAP: 3153a2116ed2SArnd Bergmann case SIOCSIFMAP: 3154a2116ed2SArnd Bergmann return compat_sioc_ifmap(net, cmd, argp); 31556b96018bSArnd Bergmann case SIOCBONDENSLAVE: 31566b96018bSArnd Bergmann case SIOCBONDRELEASE: 31576b96018bSArnd Bergmann case SIOCBONDSETHWADDR: 31586b96018bSArnd Bergmann case SIOCBONDSLAVEINFOQUERY: 31596b96018bSArnd Bergmann case SIOCBONDINFOQUERY: 31606b96018bSArnd Bergmann case SIOCBONDCHANGEACTIVE: 31616b96018bSArnd Bergmann return bond_ioctl(net, cmd, argp); 31626b96018bSArnd Bergmann case SIOCADDRT: 31636b96018bSArnd Bergmann case SIOCDELRT: 31646b96018bSArnd Bergmann return routing_ioctl(net, sock, cmd, argp); 31656b96018bSArnd Bergmann case SIOCGSTAMP: 31666b96018bSArnd Bergmann return do_siocgstamp(net, sock, cmd, argp); 31676b96018bSArnd Bergmann case SIOCGSTAMPNS: 31686b96018bSArnd Bergmann return do_siocgstampns(net, sock, cmd, argp); 3169a2116ed2SArnd Bergmann case SIOCSHWTSTAMP: 3170a2116ed2SArnd Bergmann return compat_siocshwtstamp(net, argp); 31717a229387SArnd Bergmann 31726b96018bSArnd Bergmann case FIOSETOWN: 31736b96018bSArnd Bergmann case SIOCSPGRP: 31746b96018bSArnd Bergmann case FIOGETOWN: 31756b96018bSArnd Bergmann case SIOCGPGRP: 31766b96018bSArnd Bergmann case SIOCBRADDBR: 31776b96018bSArnd Bergmann case SIOCBRDELBR: 31786b96018bSArnd Bergmann case SIOCGIFVLAN: 31796b96018bSArnd Bergmann case SIOCSIFVLAN: 31806b96018bSArnd Bergmann case SIOCADDDLCI: 31816b96018bSArnd Bergmann case SIOCDELDLCI: 31826b96018bSArnd Bergmann return sock_ioctl(file, cmd, arg); 31836b96018bSArnd Bergmann 31846b96018bSArnd Bergmann case SIOCGIFFLAGS: 31856b96018bSArnd Bergmann case SIOCSIFFLAGS: 31866b96018bSArnd Bergmann case SIOCGIFMETRIC: 31876b96018bSArnd Bergmann case SIOCSIFMETRIC: 31886b96018bSArnd Bergmann case SIOCGIFMTU: 31896b96018bSArnd Bergmann case SIOCSIFMTU: 31906b96018bSArnd Bergmann case SIOCGIFMEM: 31916b96018bSArnd Bergmann case SIOCSIFMEM: 31926b96018bSArnd Bergmann case SIOCGIFHWADDR: 31936b96018bSArnd Bergmann case SIOCSIFHWADDR: 31946b96018bSArnd Bergmann case SIOCADDMULTI: 31956b96018bSArnd Bergmann case SIOCDELMULTI: 31966b96018bSArnd Bergmann case SIOCGIFINDEX: 31976b96018bSArnd Bergmann case SIOCGIFADDR: 31986b96018bSArnd Bergmann case SIOCSIFADDR: 31996b96018bSArnd Bergmann case SIOCSIFHWBROADCAST: 32006b96018bSArnd Bergmann case SIOCDIFADDR: 32016b96018bSArnd Bergmann case SIOCGIFBRDADDR: 32026b96018bSArnd Bergmann case SIOCSIFBRDADDR: 32036b96018bSArnd Bergmann case SIOCGIFDSTADDR: 32046b96018bSArnd Bergmann case SIOCSIFDSTADDR: 32056b96018bSArnd Bergmann case SIOCGIFNETMASK: 32066b96018bSArnd Bergmann case SIOCSIFNETMASK: 32076b96018bSArnd Bergmann case SIOCSIFPFLAGS: 32086b96018bSArnd Bergmann case SIOCGIFPFLAGS: 32096b96018bSArnd Bergmann case SIOCGIFTXQLEN: 32106b96018bSArnd Bergmann case SIOCSIFTXQLEN: 32116b96018bSArnd Bergmann case SIOCBRADDIF: 32126b96018bSArnd Bergmann case SIOCBRDELIF: 32139177efd3SArnd Bergmann case SIOCSIFNAME: 32149177efd3SArnd Bergmann case SIOCGMIIPHY: 32159177efd3SArnd Bergmann case SIOCGMIIREG: 32169177efd3SArnd Bergmann case SIOCSMIIREG: 32176b96018bSArnd Bergmann return dev_ifsioc(net, sock, cmd, argp); 32189177efd3SArnd Bergmann 32196b96018bSArnd Bergmann case SIOCSARP: 32206b96018bSArnd Bergmann case SIOCGARP: 32216b96018bSArnd Bergmann case SIOCDARP: 32226b96018bSArnd Bergmann case SIOCATMARK: 32239177efd3SArnd Bergmann return sock_do_ioctl(net, sock, cmd, arg); 32249177efd3SArnd Bergmann } 32259177efd3SArnd Bergmann 32266b96018bSArnd Bergmann return -ENOIOCTLCMD; 32276b96018bSArnd Bergmann } 32287a229387SArnd Bergmann 322995c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd, 323089bbfc95SShaun Pereira unsigned long arg) 323189bbfc95SShaun Pereira { 323289bbfc95SShaun Pereira struct socket *sock = file->private_data; 323389bbfc95SShaun Pereira int ret = -ENOIOCTLCMD; 323487de87d5SDavid S. Miller struct sock *sk; 323587de87d5SDavid S. Miller struct net *net; 323687de87d5SDavid S. Miller 323787de87d5SDavid S. Miller sk = sock->sk; 323887de87d5SDavid S. Miller net = sock_net(sk); 323989bbfc95SShaun Pereira 324089bbfc95SShaun Pereira if (sock->ops->compat_ioctl) 324189bbfc95SShaun Pereira ret = sock->ops->compat_ioctl(sock, cmd, arg); 324289bbfc95SShaun Pereira 324387de87d5SDavid S. Miller if (ret == -ENOIOCTLCMD && 324487de87d5SDavid S. Miller (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) 324587de87d5SDavid S. Miller ret = compat_wext_handle_ioctl(net, cmd, arg); 324687de87d5SDavid S. Miller 32476b96018bSArnd Bergmann if (ret == -ENOIOCTLCMD) 32486b96018bSArnd Bergmann ret = compat_sock_ioctl_trans(file, sock, cmd, arg); 32496b96018bSArnd Bergmann 325089bbfc95SShaun Pereira return ret; 325189bbfc95SShaun Pereira } 325289bbfc95SShaun Pereira #endif 325389bbfc95SShaun Pereira 3254ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) 3255ac5a488eSSridhar Samudrala { 3256ac5a488eSSridhar Samudrala return sock->ops->bind(sock, addr, addrlen); 3257ac5a488eSSridhar Samudrala } 3258c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind); 3259ac5a488eSSridhar Samudrala 3260ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog) 3261ac5a488eSSridhar Samudrala { 3262ac5a488eSSridhar Samudrala return sock->ops->listen(sock, backlog); 3263ac5a488eSSridhar Samudrala } 3264c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen); 3265ac5a488eSSridhar Samudrala 3266ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags) 3267ac5a488eSSridhar Samudrala { 3268ac5a488eSSridhar Samudrala struct sock *sk = sock->sk; 3269ac5a488eSSridhar Samudrala int err; 3270ac5a488eSSridhar Samudrala 3271ac5a488eSSridhar Samudrala err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, 3272ac5a488eSSridhar Samudrala newsock); 3273ac5a488eSSridhar Samudrala if (err < 0) 3274ac5a488eSSridhar Samudrala goto done; 3275ac5a488eSSridhar Samudrala 3276ac5a488eSSridhar Samudrala err = sock->ops->accept(sock, *newsock, flags); 3277ac5a488eSSridhar Samudrala if (err < 0) { 3278ac5a488eSSridhar Samudrala sock_release(*newsock); 3279fa8705b0STony Battersby *newsock = NULL; 3280ac5a488eSSridhar Samudrala goto done; 3281ac5a488eSSridhar Samudrala } 3282ac5a488eSSridhar Samudrala 3283ac5a488eSSridhar Samudrala (*newsock)->ops = sock->ops; 32841b08534eSWei Yongjun __module_get((*newsock)->ops->owner); 3285ac5a488eSSridhar Samudrala 3286ac5a488eSSridhar Samudrala done: 3287ac5a488eSSridhar Samudrala return err; 3288ac5a488eSSridhar Samudrala } 3289c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept); 3290ac5a488eSSridhar Samudrala 3291ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, 3292ac5a488eSSridhar Samudrala int flags) 3293ac5a488eSSridhar Samudrala { 3294ac5a488eSSridhar Samudrala return sock->ops->connect(sock, addr, addrlen, flags); 3295ac5a488eSSridhar Samudrala } 3296c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect); 3297ac5a488eSSridhar Samudrala 3298ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr, 3299ac5a488eSSridhar Samudrala int *addrlen) 3300ac5a488eSSridhar Samudrala { 3301ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 0); 3302ac5a488eSSridhar Samudrala } 3303c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname); 3304ac5a488eSSridhar Samudrala 3305ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr, 3306ac5a488eSSridhar Samudrala int *addrlen) 3307ac5a488eSSridhar Samudrala { 3308ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 1); 3309ac5a488eSSridhar Samudrala } 3310c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername); 3311ac5a488eSSridhar Samudrala 3312ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname, 3313ac5a488eSSridhar Samudrala char *optval, int *optlen) 3314ac5a488eSSridhar Samudrala { 3315ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3316fb8621bbSNamhyung Kim char __user *uoptval; 3317fb8621bbSNamhyung Kim int __user *uoptlen; 3318ac5a488eSSridhar Samudrala int err; 3319ac5a488eSSridhar Samudrala 3320fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3321fb8621bbSNamhyung Kim uoptlen = (int __user __force *) optlen; 3322fb8621bbSNamhyung Kim 3323ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3324ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3325fb8621bbSNamhyung Kim err = sock_getsockopt(sock, level, optname, uoptval, uoptlen); 3326ac5a488eSSridhar Samudrala else 3327fb8621bbSNamhyung Kim err = sock->ops->getsockopt(sock, level, optname, uoptval, 3328fb8621bbSNamhyung Kim uoptlen); 3329ac5a488eSSridhar Samudrala set_fs(oldfs); 3330ac5a488eSSridhar Samudrala return err; 3331ac5a488eSSridhar Samudrala } 3332c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt); 3333ac5a488eSSridhar Samudrala 3334ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname, 3335b7058842SDavid S. Miller char *optval, unsigned int optlen) 3336ac5a488eSSridhar Samudrala { 3337ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3338fb8621bbSNamhyung Kim char __user *uoptval; 3339ac5a488eSSridhar Samudrala int err; 3340ac5a488eSSridhar Samudrala 3341fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3342fb8621bbSNamhyung Kim 3343ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3344ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3345fb8621bbSNamhyung Kim err = sock_setsockopt(sock, level, optname, uoptval, optlen); 3346ac5a488eSSridhar Samudrala else 3347fb8621bbSNamhyung Kim err = sock->ops->setsockopt(sock, level, optname, uoptval, 3348ac5a488eSSridhar Samudrala optlen); 3349ac5a488eSSridhar Samudrala set_fs(oldfs); 3350ac5a488eSSridhar Samudrala return err; 3351ac5a488eSSridhar Samudrala } 3352c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt); 3353ac5a488eSSridhar Samudrala 3354ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset, 3355ac5a488eSSridhar Samudrala size_t size, int flags) 3356ac5a488eSSridhar Samudrala { 3357f8451725SHerbert Xu sock_update_classid(sock->sk); 3358f8451725SHerbert Xu 3359ac5a488eSSridhar Samudrala if (sock->ops->sendpage) 3360ac5a488eSSridhar Samudrala return sock->ops->sendpage(sock, page, offset, size, flags); 3361ac5a488eSSridhar Samudrala 3362ac5a488eSSridhar Samudrala return sock_no_sendpage(sock, page, offset, size, flags); 3363ac5a488eSSridhar Samudrala } 3364c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage); 3365ac5a488eSSridhar Samudrala 3366ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg) 3367ac5a488eSSridhar Samudrala { 3368ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3369ac5a488eSSridhar Samudrala int err; 3370ac5a488eSSridhar Samudrala 3371ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3372ac5a488eSSridhar Samudrala err = sock->ops->ioctl(sock, cmd, arg); 3373ac5a488eSSridhar Samudrala set_fs(oldfs); 3374ac5a488eSSridhar Samudrala 3375ac5a488eSSridhar Samudrala return err; 3376ac5a488eSSridhar Samudrala } 3377c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl); 3378ac5a488eSSridhar Samudrala 337991cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) 338091cf45f0STrond Myklebust { 338191cf45f0STrond Myklebust return sock->ops->shutdown(sock, how); 338291cf45f0STrond Myklebust } 338391cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown); 3384