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 184230b1839SYOSHIFUJI Hideaki int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *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 21211165f14Sstephen hemminger static int move_addr_to_user(struct sockaddr *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 4016cb153caSBenjamin LaHaise static 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 } 4096cb153caSBenjamin LaHaise 4101da177e4SLinus Torvalds /** 4111da177e4SLinus Torvalds * sockfd_lookup - Go from a file number to its socket slot 4121da177e4SLinus Torvalds * @fd: file handle 4131da177e4SLinus Torvalds * @err: pointer to an error code return 4141da177e4SLinus Torvalds * 4151da177e4SLinus Torvalds * The file handle passed in is locked and the socket it is bound 4161da177e4SLinus Torvalds * too is returned. If an error occurs the err pointer is overwritten 4171da177e4SLinus Torvalds * with a negative errno code and NULL is returned. The function checks 4181da177e4SLinus Torvalds * for both invalid handles and passing a handle which is not a socket. 4191da177e4SLinus Torvalds * 4201da177e4SLinus Torvalds * On a success the socket object pointer is returned. 4211da177e4SLinus Torvalds */ 4221da177e4SLinus Torvalds 4231da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err) 4241da177e4SLinus Torvalds { 4251da177e4SLinus Torvalds struct file *file; 4261da177e4SLinus Torvalds struct socket *sock; 4271da177e4SLinus Torvalds 42889bddce5SStephen Hemminger file = fget(fd); 42989bddce5SStephen Hemminger if (!file) { 4301da177e4SLinus Torvalds *err = -EBADF; 4311da177e4SLinus Torvalds return NULL; 4321da177e4SLinus Torvalds } 43389bddce5SStephen Hemminger 4346cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4356cb153caSBenjamin LaHaise if (!sock) 4361da177e4SLinus Torvalds fput(file); 4376cb153caSBenjamin LaHaise return sock; 4381da177e4SLinus Torvalds } 439c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup); 4401da177e4SLinus Torvalds 4416cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) 4426cb153caSBenjamin LaHaise { 4436cb153caSBenjamin LaHaise struct file *file; 4446cb153caSBenjamin LaHaise struct socket *sock; 4456cb153caSBenjamin LaHaise 4463672558cSHua Zhong *err = -EBADF; 4476cb153caSBenjamin LaHaise file = fget_light(fd, fput_needed); 4486cb153caSBenjamin LaHaise if (file) { 4496cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4506cb153caSBenjamin LaHaise if (sock) 4511da177e4SLinus Torvalds return sock; 4526cb153caSBenjamin LaHaise fput_light(file, *fput_needed); 4536cb153caSBenjamin LaHaise } 4546cb153caSBenjamin LaHaise return NULL; 4551da177e4SLinus Torvalds } 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds /** 4581da177e4SLinus Torvalds * sock_alloc - allocate a socket 4591da177e4SLinus Torvalds * 4601da177e4SLinus Torvalds * Allocate a new inode and socket object. The two are bound together 4611da177e4SLinus Torvalds * and initialised. The socket is then returned. If we are out of inodes 4621da177e4SLinus Torvalds * NULL is returned. 4631da177e4SLinus Torvalds */ 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds static struct socket *sock_alloc(void) 4661da177e4SLinus Torvalds { 4671da177e4SLinus Torvalds struct inode *inode; 4681da177e4SLinus Torvalds struct socket *sock; 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds inode = new_inode(sock_mnt->mnt_sb); 4711da177e4SLinus Torvalds if (!inode) 4721da177e4SLinus Torvalds return NULL; 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds sock = SOCKET_I(inode); 4751da177e4SLinus Torvalds 47629a020d3SEric Dumazet kmemcheck_annotate_bitfield(sock, type); 47785fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 4781da177e4SLinus Torvalds inode->i_mode = S_IFSOCK | S_IRWXUGO; 4798192b0c4SDavid Howells inode->i_uid = current_fsuid(); 4808192b0c4SDavid Howells inode->i_gid = current_fsgid(); 4811da177e4SLinus Torvalds 4824e69489aSEric Dumazet percpu_add(sockets_in_use, 1); 4831da177e4SLinus Torvalds return sock; 4841da177e4SLinus Torvalds } 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds /* 4871da177e4SLinus Torvalds * In theory you can't get an open on this inode, but /proc provides 4881da177e4SLinus Torvalds * a back door. Remember to keep it shut otherwise you'll let the 4891da177e4SLinus Torvalds * creepy crawlies in. 4901da177e4SLinus Torvalds */ 4911da177e4SLinus Torvalds 4921da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare) 4931da177e4SLinus Torvalds { 4941da177e4SLinus Torvalds return -ENXIO; 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds 4974b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = { 4981da177e4SLinus Torvalds .owner = THIS_MODULE, 4991da177e4SLinus Torvalds .open = sock_no_open, 5006038f373SArnd Bergmann .llseek = noop_llseek, 5011da177e4SLinus Torvalds }; 5021da177e4SLinus Torvalds 5031da177e4SLinus Torvalds /** 5041da177e4SLinus Torvalds * sock_release - close a socket 5051da177e4SLinus Torvalds * @sock: socket to close 5061da177e4SLinus Torvalds * 5071da177e4SLinus Torvalds * The socket is released from the protocol stack if it has a release 5081da177e4SLinus Torvalds * callback, and the inode is then released if the socket is bound to 5091da177e4SLinus Torvalds * an inode not a file. 5101da177e4SLinus Torvalds */ 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds void sock_release(struct socket *sock) 5131da177e4SLinus Torvalds { 5141da177e4SLinus Torvalds if (sock->ops) { 5151da177e4SLinus Torvalds struct module *owner = sock->ops->owner; 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds sock->ops->release(sock); 5181da177e4SLinus Torvalds sock->ops = NULL; 5191da177e4SLinus Torvalds module_put(owner); 5201da177e4SLinus Torvalds } 5211da177e4SLinus Torvalds 522eaefd110SEric Dumazet if (rcu_dereference_protected(sock->wq, 1)->fasync_list) 5231da177e4SLinus Torvalds printk(KERN_ERR "sock_release: fasync list not empty!\n"); 5241da177e4SLinus Torvalds 5254e69489aSEric Dumazet percpu_sub(sockets_in_use, 1); 5261da177e4SLinus Torvalds if (!sock->file) { 5271da177e4SLinus Torvalds iput(SOCK_INODE(sock)); 5281da177e4SLinus Torvalds return; 5291da177e4SLinus Torvalds } 5301da177e4SLinus Torvalds sock->file = NULL; 5311da177e4SLinus Torvalds } 532c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release); 5331da177e4SLinus Torvalds 5342244d07bSOliver Hartkopp int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) 53520d49473SPatrick Ohly { 5362244d07bSOliver Hartkopp *tx_flags = 0; 53720d49473SPatrick Ohly if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) 5382244d07bSOliver Hartkopp *tx_flags |= SKBTX_HW_TSTAMP; 53920d49473SPatrick Ohly if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) 5402244d07bSOliver Hartkopp *tx_flags |= SKBTX_SW_TSTAMP; 54120d49473SPatrick Ohly return 0; 54220d49473SPatrick Ohly } 54320d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp); 54420d49473SPatrick Ohly 545228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock, 5461da177e4SLinus Torvalds struct msghdr *msg, size_t size) 5471da177e4SLinus Torvalds { 5481da177e4SLinus Torvalds struct sock_iocb *si = kiocb_to_siocb(iocb); 5491da177e4SLinus Torvalds 550f8451725SHerbert Xu sock_update_classid(sock->sk); 551f8451725SHerbert Xu 5521da177e4SLinus Torvalds si->sock = sock; 5531da177e4SLinus Torvalds si->scm = NULL; 5541da177e4SLinus Torvalds si->msg = msg; 5551da177e4SLinus Torvalds si->size = size; 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvalds return sock->ops->sendmsg(iocb, sock, msg, size); 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds 560228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, 561228e548eSAnton Blanchard struct msghdr *msg, size_t size) 562228e548eSAnton Blanchard { 563228e548eSAnton Blanchard int err = security_socket_sendmsg(sock, msg, size); 564228e548eSAnton Blanchard 565228e548eSAnton Blanchard return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size); 566228e548eSAnton Blanchard } 567228e548eSAnton Blanchard 5681da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) 5691da177e4SLinus Torvalds { 5701da177e4SLinus Torvalds struct kiocb iocb; 5711da177e4SLinus Torvalds struct sock_iocb siocb; 5721da177e4SLinus Torvalds int ret; 5731da177e4SLinus Torvalds 5741da177e4SLinus Torvalds init_sync_kiocb(&iocb, NULL); 5751da177e4SLinus Torvalds iocb.private = &siocb; 5761da177e4SLinus Torvalds ret = __sock_sendmsg(&iocb, sock, msg, size); 5771da177e4SLinus Torvalds if (-EIOCBQUEUED == ret) 5781da177e4SLinus Torvalds ret = wait_on_sync_kiocb(&iocb); 5791da177e4SLinus Torvalds return ret; 5801da177e4SLinus Torvalds } 581c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg); 5821da177e4SLinus Torvalds 583894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size) 584228e548eSAnton Blanchard { 585228e548eSAnton Blanchard struct kiocb iocb; 586228e548eSAnton Blanchard struct sock_iocb siocb; 587228e548eSAnton Blanchard int ret; 588228e548eSAnton Blanchard 589228e548eSAnton Blanchard init_sync_kiocb(&iocb, NULL); 590228e548eSAnton Blanchard iocb.private = &siocb; 591228e548eSAnton Blanchard ret = __sock_sendmsg_nosec(&iocb, sock, msg, size); 592228e548eSAnton Blanchard if (-EIOCBQUEUED == ret) 593228e548eSAnton Blanchard ret = wait_on_sync_kiocb(&iocb); 594228e548eSAnton Blanchard return ret; 595228e548eSAnton Blanchard } 596228e548eSAnton Blanchard 5971da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg, 5981da177e4SLinus Torvalds struct kvec *vec, size_t num, size_t size) 5991da177e4SLinus Torvalds { 6001da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 6011da177e4SLinus Torvalds int result; 6021da177e4SLinus Torvalds 6031da177e4SLinus Torvalds set_fs(KERNEL_DS); 6041da177e4SLinus Torvalds /* 6051da177e4SLinus Torvalds * the following is safe, since for compiler definitions of kvec and 6061da177e4SLinus Torvalds * iovec are identical, yielding the same in-core layout and alignment 6071da177e4SLinus Torvalds */ 60889bddce5SStephen Hemminger msg->msg_iov = (struct iovec *)vec; 6091da177e4SLinus Torvalds msg->msg_iovlen = num; 6101da177e4SLinus Torvalds result = sock_sendmsg(sock, msg, size); 6111da177e4SLinus Torvalds set_fs(oldfs); 6121da177e4SLinus Torvalds return result; 6131da177e4SLinus Torvalds } 614c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg); 6151da177e4SLinus Torvalds 61620d49473SPatrick Ohly static int ktime2ts(ktime_t kt, struct timespec *ts) 61720d49473SPatrick Ohly { 61820d49473SPatrick Ohly if (kt.tv64) { 61920d49473SPatrick Ohly *ts = ktime_to_timespec(kt); 62020d49473SPatrick Ohly return 1; 62120d49473SPatrick Ohly } else { 62220d49473SPatrick Ohly return 0; 62320d49473SPatrick Ohly } 62420d49473SPatrick Ohly } 62520d49473SPatrick Ohly 62692f37fd2SEric Dumazet /* 62792f37fd2SEric Dumazet * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) 62892f37fd2SEric Dumazet */ 62992f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 63092f37fd2SEric Dumazet struct sk_buff *skb) 63192f37fd2SEric Dumazet { 63220d49473SPatrick Ohly int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 63320d49473SPatrick Ohly struct timespec ts[3]; 63420d49473SPatrick Ohly int empty = 1; 63520d49473SPatrick Ohly struct skb_shared_hwtstamps *shhwtstamps = 63620d49473SPatrick Ohly skb_hwtstamps(skb); 63792f37fd2SEric Dumazet 63820d49473SPatrick Ohly /* Race occurred between timestamp enabling and packet 63920d49473SPatrick Ohly receiving. Fill in the current time for now. */ 64020d49473SPatrick Ohly if (need_software_tstamp && skb->tstamp.tv64 == 0) 64120d49473SPatrick Ohly __net_timestamp(skb); 64220d49473SPatrick Ohly 64320d49473SPatrick Ohly if (need_software_tstamp) { 64492f37fd2SEric Dumazet if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { 64592f37fd2SEric Dumazet struct timeval tv; 64620d49473SPatrick Ohly skb_get_timestamp(skb, &tv); 64720d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, 64820d49473SPatrick Ohly sizeof(tv), &tv); 64992f37fd2SEric Dumazet } else { 650842509b8SHagen Paul Pfeifer skb_get_timestampns(skb, &ts[0]); 65120d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, 652842509b8SHagen Paul Pfeifer sizeof(ts[0]), &ts[0]); 65392f37fd2SEric Dumazet } 65492f37fd2SEric Dumazet } 65592f37fd2SEric Dumazet 65620d49473SPatrick Ohly 65720d49473SPatrick Ohly memset(ts, 0, sizeof(ts)); 65820d49473SPatrick Ohly if (skb->tstamp.tv64 && 65920d49473SPatrick Ohly sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) { 66020d49473SPatrick Ohly skb_get_timestampns(skb, ts + 0); 66120d49473SPatrick Ohly empty = 0; 66220d49473SPatrick Ohly } 66320d49473SPatrick Ohly if (shhwtstamps) { 66420d49473SPatrick Ohly if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) && 66520d49473SPatrick Ohly ktime2ts(shhwtstamps->syststamp, ts + 1)) 66620d49473SPatrick Ohly empty = 0; 66720d49473SPatrick Ohly if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && 66820d49473SPatrick Ohly ktime2ts(shhwtstamps->hwtstamp, ts + 2)) 66920d49473SPatrick Ohly empty = 0; 67020d49473SPatrick Ohly } 67120d49473SPatrick Ohly if (!empty) 67220d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, 67320d49473SPatrick Ohly SCM_TIMESTAMPING, sizeof(ts), &ts); 67420d49473SPatrick Ohly } 6757c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 6767c81fd8bSArnaldo Carvalho de Melo 67711165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, 67811165f14Sstephen hemminger struct sk_buff *skb) 6793b885787SNeil Horman { 6803b885787SNeil Horman if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount) 6813b885787SNeil Horman put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, 6823b885787SNeil Horman sizeof(__u32), &skb->dropcount); 6833b885787SNeil Horman } 6843b885787SNeil Horman 685767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 6863b885787SNeil Horman struct sk_buff *skb) 6873b885787SNeil Horman { 6883b885787SNeil Horman sock_recv_timestamp(msg, sk, skb); 6893b885787SNeil Horman sock_recv_drops(msg, sk, skb); 6903b885787SNeil Horman } 691767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); 6923b885787SNeil Horman 693a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, 6941da177e4SLinus Torvalds struct msghdr *msg, size_t size, int flags) 6951da177e4SLinus Torvalds { 6961da177e4SLinus Torvalds struct sock_iocb *si = kiocb_to_siocb(iocb); 6971da177e4SLinus Torvalds 698f8451725SHerbert Xu sock_update_classid(sock->sk); 699f8451725SHerbert Xu 7001da177e4SLinus Torvalds si->sock = sock; 7011da177e4SLinus Torvalds si->scm = NULL; 7021da177e4SLinus Torvalds si->msg = msg; 7031da177e4SLinus Torvalds si->size = size; 7041da177e4SLinus Torvalds si->flags = flags; 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds return sock->ops->recvmsg(iocb, sock, msg, size, flags); 7071da177e4SLinus Torvalds } 7081da177e4SLinus Torvalds 709a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, 710a2e27255SArnaldo Carvalho de Melo struct msghdr *msg, size_t size, int flags) 711a2e27255SArnaldo Carvalho de Melo { 712a2e27255SArnaldo Carvalho de Melo int err = security_socket_recvmsg(sock, msg, size, flags); 713a2e27255SArnaldo Carvalho de Melo 714a2e27255SArnaldo Carvalho de Melo return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags); 715a2e27255SArnaldo Carvalho de Melo } 716a2e27255SArnaldo Carvalho de Melo 7171da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg, 7181da177e4SLinus Torvalds size_t size, int flags) 7191da177e4SLinus Torvalds { 7201da177e4SLinus Torvalds struct kiocb iocb; 7211da177e4SLinus Torvalds struct sock_iocb siocb; 7221da177e4SLinus Torvalds int ret; 7231da177e4SLinus Torvalds 7241da177e4SLinus Torvalds init_sync_kiocb(&iocb, NULL); 7251da177e4SLinus Torvalds iocb.private = &siocb; 7261da177e4SLinus Torvalds ret = __sock_recvmsg(&iocb, sock, msg, size, flags); 7271da177e4SLinus Torvalds if (-EIOCBQUEUED == ret) 7281da177e4SLinus Torvalds ret = wait_on_sync_kiocb(&iocb); 7291da177e4SLinus Torvalds return ret; 7301da177e4SLinus Torvalds } 731c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg); 7321da177e4SLinus Torvalds 733a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, 734a2e27255SArnaldo Carvalho de Melo size_t size, int flags) 735a2e27255SArnaldo Carvalho de Melo { 736a2e27255SArnaldo Carvalho de Melo struct kiocb iocb; 737a2e27255SArnaldo Carvalho de Melo struct sock_iocb siocb; 738a2e27255SArnaldo Carvalho de Melo int ret; 739a2e27255SArnaldo Carvalho de Melo 740a2e27255SArnaldo Carvalho de Melo init_sync_kiocb(&iocb, NULL); 741a2e27255SArnaldo Carvalho de Melo iocb.private = &siocb; 742a2e27255SArnaldo Carvalho de Melo ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags); 743a2e27255SArnaldo Carvalho de Melo if (-EIOCBQUEUED == ret) 744a2e27255SArnaldo Carvalho de Melo ret = wait_on_sync_kiocb(&iocb); 745a2e27255SArnaldo Carvalho de Melo return ret; 746a2e27255SArnaldo Carvalho de Melo } 747a2e27255SArnaldo Carvalho de Melo 748c1249c0aSMartin Lucina /** 749c1249c0aSMartin Lucina * kernel_recvmsg - Receive a message from a socket (kernel space) 750c1249c0aSMartin Lucina * @sock: The socket to receive the message from 751c1249c0aSMartin Lucina * @msg: Received message 752c1249c0aSMartin Lucina * @vec: Input s/g array for message data 753c1249c0aSMartin Lucina * @num: Size of input s/g array 754c1249c0aSMartin Lucina * @size: Number of bytes to read 755c1249c0aSMartin Lucina * @flags: Message flags (MSG_DONTWAIT, etc...) 756c1249c0aSMartin Lucina * 757c1249c0aSMartin Lucina * On return the msg structure contains the scatter/gather array passed in the 758c1249c0aSMartin Lucina * vec argument. The array is modified so that it consists of the unfilled 759c1249c0aSMartin Lucina * portion of the original array. 760c1249c0aSMartin Lucina * 761c1249c0aSMartin Lucina * The returned value is the total number of bytes received, or an error. 762c1249c0aSMartin Lucina */ 7631da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg, 76489bddce5SStephen Hemminger struct kvec *vec, size_t num, size_t size, int flags) 7651da177e4SLinus Torvalds { 7661da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 7671da177e4SLinus Torvalds int result; 7681da177e4SLinus Torvalds 7691da177e4SLinus Torvalds set_fs(KERNEL_DS); 7701da177e4SLinus Torvalds /* 7711da177e4SLinus Torvalds * the following is safe, since for compiler definitions of kvec and 7721da177e4SLinus Torvalds * iovec are identical, yielding the same in-core layout and alignment 7731da177e4SLinus Torvalds */ 77489bddce5SStephen Hemminger msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num; 7751da177e4SLinus Torvalds result = sock_recvmsg(sock, msg, size, flags); 7761da177e4SLinus Torvalds set_fs(oldfs); 7771da177e4SLinus Torvalds return result; 7781da177e4SLinus Torvalds } 779c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg); 7801da177e4SLinus Torvalds 7811da177e4SLinus Torvalds static void sock_aio_dtor(struct kiocb *iocb) 7821da177e4SLinus Torvalds { 7831da177e4SLinus Torvalds kfree(iocb->private); 7841da177e4SLinus Torvalds } 7851da177e4SLinus Torvalds 78620380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page, 7871da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more) 7881da177e4SLinus Torvalds { 7891da177e4SLinus Torvalds struct socket *sock; 7901da177e4SLinus Torvalds int flags; 7911da177e4SLinus Torvalds 792b69aee04SEric Dumazet sock = file->private_data; 7931da177e4SLinus Torvalds 7941da177e4SLinus Torvalds flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT; 7951da177e4SLinus Torvalds if (more) 7961da177e4SLinus Torvalds flags |= MSG_MORE; 7971da177e4SLinus Torvalds 798e6949583SLinus Torvalds return kernel_sendpage(sock, page, offset, size, flags); 7991da177e4SLinus Torvalds } 8001da177e4SLinus Torvalds 8019c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 8029c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 8039c55e01cSJens Axboe unsigned int flags) 8049c55e01cSJens Axboe { 8059c55e01cSJens Axboe struct socket *sock = file->private_data; 8069c55e01cSJens Axboe 807997b37daSRémi Denis-Courmont if (unlikely(!sock->ops->splice_read)) 808997b37daSRémi Denis-Courmont return -EINVAL; 809997b37daSRémi Denis-Courmont 810f8451725SHerbert Xu sock_update_classid(sock->sk); 811f8451725SHerbert Xu 8129c55e01cSJens Axboe return sock->ops->splice_read(sock, ppos, pipe, len, flags); 8139c55e01cSJens Axboe } 8149c55e01cSJens Axboe 815ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, 81689bddce5SStephen Hemminger struct sock_iocb *siocb) 817ce1d4d3eSChristoph Hellwig { 818ce1d4d3eSChristoph Hellwig if (!is_sync_kiocb(iocb)) { 819ce1d4d3eSChristoph Hellwig siocb = kmalloc(sizeof(*siocb), GFP_KERNEL); 820ce1d4d3eSChristoph Hellwig if (!siocb) 821ce1d4d3eSChristoph Hellwig return NULL; 822ce1d4d3eSChristoph Hellwig iocb->ki_dtor = sock_aio_dtor; 823ce1d4d3eSChristoph Hellwig } 824ce1d4d3eSChristoph Hellwig 825ce1d4d3eSChristoph Hellwig siocb->kiocb = iocb; 826ce1d4d3eSChristoph Hellwig iocb->private = siocb; 827ce1d4d3eSChristoph Hellwig return siocb; 828ce1d4d3eSChristoph Hellwig } 829ce1d4d3eSChristoph Hellwig 830ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, 831027445c3SBadari Pulavarty struct file *file, const struct iovec *iov, 83289bddce5SStephen Hemminger unsigned long nr_segs) 833ce1d4d3eSChristoph Hellwig { 834ce1d4d3eSChristoph Hellwig struct socket *sock = file->private_data; 835ce1d4d3eSChristoph Hellwig size_t size = 0; 836ce1d4d3eSChristoph Hellwig int i; 837ce1d4d3eSChristoph Hellwig 838ce1d4d3eSChristoph Hellwig for (i = 0; i < nr_segs; i++) 839ce1d4d3eSChristoph Hellwig size += iov[i].iov_len; 840ce1d4d3eSChristoph Hellwig 841ce1d4d3eSChristoph Hellwig msg->msg_name = NULL; 842ce1d4d3eSChristoph Hellwig msg->msg_namelen = 0; 843ce1d4d3eSChristoph Hellwig msg->msg_control = NULL; 844ce1d4d3eSChristoph Hellwig msg->msg_controllen = 0; 845ce1d4d3eSChristoph Hellwig msg->msg_iov = (struct iovec *)iov; 846ce1d4d3eSChristoph Hellwig msg->msg_iovlen = nr_segs; 847ce1d4d3eSChristoph Hellwig msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 848ce1d4d3eSChristoph Hellwig 849ce1d4d3eSChristoph Hellwig return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags); 850ce1d4d3eSChristoph Hellwig } 851ce1d4d3eSChristoph Hellwig 852027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, 853027445c3SBadari Pulavarty unsigned long nr_segs, loff_t pos) 854ce1d4d3eSChristoph Hellwig { 855ce1d4d3eSChristoph Hellwig struct sock_iocb siocb, *x; 856ce1d4d3eSChristoph Hellwig 857ce1d4d3eSChristoph Hellwig if (pos != 0) 858ce1d4d3eSChristoph Hellwig return -ESPIPE; 859027445c3SBadari Pulavarty 860027445c3SBadari Pulavarty if (iocb->ki_left == 0) /* Match SYS5 behaviour */ 861ce1d4d3eSChristoph Hellwig return 0; 862ce1d4d3eSChristoph Hellwig 863027445c3SBadari Pulavarty 864027445c3SBadari Pulavarty x = alloc_sock_iocb(iocb, &siocb); 865ce1d4d3eSChristoph Hellwig if (!x) 866ce1d4d3eSChristoph Hellwig return -ENOMEM; 867027445c3SBadari Pulavarty return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs); 868ce1d4d3eSChristoph Hellwig } 869ce1d4d3eSChristoph Hellwig 870ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, 871027445c3SBadari Pulavarty struct file *file, const struct iovec *iov, 87289bddce5SStephen Hemminger unsigned long nr_segs) 873ce1d4d3eSChristoph Hellwig { 874ce1d4d3eSChristoph Hellwig struct socket *sock = file->private_data; 875ce1d4d3eSChristoph Hellwig size_t size = 0; 876ce1d4d3eSChristoph Hellwig int i; 877ce1d4d3eSChristoph Hellwig 878ce1d4d3eSChristoph Hellwig for (i = 0; i < nr_segs; i++) 879ce1d4d3eSChristoph Hellwig size += iov[i].iov_len; 880ce1d4d3eSChristoph Hellwig 881ce1d4d3eSChristoph Hellwig msg->msg_name = NULL; 882ce1d4d3eSChristoph Hellwig msg->msg_namelen = 0; 883ce1d4d3eSChristoph Hellwig msg->msg_control = NULL; 884ce1d4d3eSChristoph Hellwig msg->msg_controllen = 0; 885ce1d4d3eSChristoph Hellwig msg->msg_iov = (struct iovec *)iov; 886ce1d4d3eSChristoph Hellwig msg->msg_iovlen = nr_segs; 887ce1d4d3eSChristoph Hellwig msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 888ce1d4d3eSChristoph Hellwig if (sock->type == SOCK_SEQPACKET) 889ce1d4d3eSChristoph Hellwig msg->msg_flags |= MSG_EOR; 890ce1d4d3eSChristoph Hellwig 891ce1d4d3eSChristoph Hellwig return __sock_sendmsg(iocb, sock, msg, size); 892ce1d4d3eSChristoph Hellwig } 893ce1d4d3eSChristoph Hellwig 894027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, 895027445c3SBadari Pulavarty unsigned long nr_segs, loff_t pos) 8961da177e4SLinus Torvalds { 897ce1d4d3eSChristoph Hellwig struct sock_iocb siocb, *x; 8981da177e4SLinus Torvalds 899ce1d4d3eSChristoph Hellwig if (pos != 0) 900ce1d4d3eSChristoph Hellwig return -ESPIPE; 901027445c3SBadari Pulavarty 902027445c3SBadari Pulavarty x = alloc_sock_iocb(iocb, &siocb); 903ce1d4d3eSChristoph Hellwig if (!x) 904ce1d4d3eSChristoph Hellwig return -ENOMEM; 905ce1d4d3eSChristoph Hellwig 906027445c3SBadari Pulavarty return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs); 9071da177e4SLinus Torvalds } 9081da177e4SLinus Torvalds 9091da177e4SLinus Torvalds /* 9101da177e4SLinus Torvalds * Atomic setting of ioctl hooks to avoid race 9111da177e4SLinus Torvalds * with module unload. 9121da177e4SLinus Torvalds */ 9131da177e4SLinus Torvalds 9144a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex); 915c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg); 9161da177e4SLinus Torvalds 917881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *)) 9181da177e4SLinus Torvalds { 9194a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 9201da177e4SLinus Torvalds br_ioctl_hook = hook; 9214a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 9221da177e4SLinus Torvalds } 9231da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set); 9241da177e4SLinus Torvalds 9254a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex); 926881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg); 9271da177e4SLinus Torvalds 928881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *)) 9291da177e4SLinus Torvalds { 9304a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 9311da177e4SLinus Torvalds vlan_ioctl_hook = hook; 9324a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 9331da177e4SLinus Torvalds } 9341da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set); 9351da177e4SLinus Torvalds 9364a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex); 9371da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *); 9381da177e4SLinus Torvalds 9391da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) 9401da177e4SLinus Torvalds { 9414a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 9421da177e4SLinus Torvalds dlci_ioctl_hook = hook; 9434a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 9441da177e4SLinus Torvalds } 9451da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set); 9461da177e4SLinus Torvalds 9476b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock, 9486b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 9496b96018bSArnd Bergmann { 9506b96018bSArnd Bergmann int err; 9516b96018bSArnd Bergmann void __user *argp = (void __user *)arg; 9526b96018bSArnd Bergmann 9536b96018bSArnd Bergmann err = sock->ops->ioctl(sock, cmd, arg); 9546b96018bSArnd Bergmann 9556b96018bSArnd Bergmann /* 9566b96018bSArnd Bergmann * If this ioctl is unknown try to hand it down 9576b96018bSArnd Bergmann * to the NIC driver. 9586b96018bSArnd Bergmann */ 9596b96018bSArnd Bergmann if (err == -ENOIOCTLCMD) 9606b96018bSArnd Bergmann err = dev_ioctl(net, cmd, argp); 9616b96018bSArnd Bergmann 9626b96018bSArnd Bergmann return err; 9636b96018bSArnd Bergmann } 9646b96018bSArnd Bergmann 9651da177e4SLinus Torvalds /* 9661da177e4SLinus Torvalds * With an ioctl, arg may well be a user mode pointer, but we don't know 9671da177e4SLinus Torvalds * what to do with it - that's up to the protocol still. 9681da177e4SLinus Torvalds */ 9691da177e4SLinus Torvalds 9701da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) 9711da177e4SLinus Torvalds { 9721da177e4SLinus Torvalds struct socket *sock; 973881d966bSEric W. Biederman struct sock *sk; 9741da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 9751da177e4SLinus Torvalds int pid, err; 976881d966bSEric W. Biederman struct net *net; 9771da177e4SLinus Torvalds 978b69aee04SEric Dumazet sock = file->private_data; 979881d966bSEric W. Biederman sk = sock->sk; 9803b1e0a65SYOSHIFUJI Hideaki net = sock_net(sk); 9811da177e4SLinus Torvalds if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { 982881d966bSEric W. Biederman err = dev_ioctl(net, cmd, argp); 9831da177e4SLinus Torvalds } else 9843d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE 9851da177e4SLinus Torvalds if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { 986881d966bSEric W. Biederman err = dev_ioctl(net, cmd, argp); 9871da177e4SLinus Torvalds } else 9883d23e349SJohannes Berg #endif 9891da177e4SLinus Torvalds switch (cmd) { 9901da177e4SLinus Torvalds case FIOSETOWN: 9911da177e4SLinus Torvalds case SIOCSPGRP: 9921da177e4SLinus Torvalds err = -EFAULT; 9931da177e4SLinus Torvalds if (get_user(pid, (int __user *)argp)) 9941da177e4SLinus Torvalds break; 9951da177e4SLinus Torvalds err = f_setown(sock->file, pid, 1); 9961da177e4SLinus Torvalds break; 9971da177e4SLinus Torvalds case FIOGETOWN: 9981da177e4SLinus Torvalds case SIOCGPGRP: 999609d7fa9SEric W. Biederman err = put_user(f_getown(sock->file), 100089bddce5SStephen Hemminger (int __user *)argp); 10011da177e4SLinus Torvalds break; 10021da177e4SLinus Torvalds case SIOCGIFBR: 10031da177e4SLinus Torvalds case SIOCSIFBR: 10041da177e4SLinus Torvalds case SIOCBRADDBR: 10051da177e4SLinus Torvalds case SIOCBRDELBR: 10061da177e4SLinus Torvalds err = -ENOPKG; 10071da177e4SLinus Torvalds if (!br_ioctl_hook) 10081da177e4SLinus Torvalds request_module("bridge"); 10091da177e4SLinus Torvalds 10104a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 10111da177e4SLinus Torvalds if (br_ioctl_hook) 1012881d966bSEric W. Biederman err = br_ioctl_hook(net, cmd, argp); 10134a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 10141da177e4SLinus Torvalds break; 10151da177e4SLinus Torvalds case SIOCGIFVLAN: 10161da177e4SLinus Torvalds case SIOCSIFVLAN: 10171da177e4SLinus Torvalds err = -ENOPKG; 10181da177e4SLinus Torvalds if (!vlan_ioctl_hook) 10191da177e4SLinus Torvalds request_module("8021q"); 10201da177e4SLinus Torvalds 10214a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 10221da177e4SLinus Torvalds if (vlan_ioctl_hook) 1023881d966bSEric W. Biederman err = vlan_ioctl_hook(net, argp); 10244a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 10251da177e4SLinus Torvalds break; 10261da177e4SLinus Torvalds case SIOCADDDLCI: 10271da177e4SLinus Torvalds case SIOCDELDLCI: 10281da177e4SLinus Torvalds err = -ENOPKG; 10291da177e4SLinus Torvalds if (!dlci_ioctl_hook) 10301da177e4SLinus Torvalds request_module("dlci"); 10311da177e4SLinus Torvalds 10324a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 10337512cbf6SPavel Emelyanov if (dlci_ioctl_hook) 10341da177e4SLinus Torvalds err = dlci_ioctl_hook(cmd, argp); 10354a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 10361da177e4SLinus Torvalds break; 10371da177e4SLinus Torvalds default: 10386b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, arg); 10391da177e4SLinus Torvalds break; 10401da177e4SLinus Torvalds } 10411da177e4SLinus Torvalds return err; 10421da177e4SLinus Torvalds } 10431da177e4SLinus Torvalds 10441da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res) 10451da177e4SLinus Torvalds { 10461da177e4SLinus Torvalds int err; 10471da177e4SLinus Torvalds struct socket *sock = NULL; 10481da177e4SLinus Torvalds 10491da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, 1); 10501da177e4SLinus Torvalds if (err) 10511da177e4SLinus Torvalds goto out; 10521da177e4SLinus Torvalds 10531da177e4SLinus Torvalds sock = sock_alloc(); 10541da177e4SLinus Torvalds if (!sock) { 10551da177e4SLinus Torvalds err = -ENOMEM; 10561da177e4SLinus Torvalds goto out; 10571da177e4SLinus Torvalds } 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds sock->type = type; 10607420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, 1); 10617420ed23SVenkat Yekkirala if (err) 10627420ed23SVenkat Yekkirala goto out_release; 10637420ed23SVenkat Yekkirala 10641da177e4SLinus Torvalds out: 10651da177e4SLinus Torvalds *res = sock; 10661da177e4SLinus Torvalds return err; 10677420ed23SVenkat Yekkirala out_release: 10687420ed23SVenkat Yekkirala sock_release(sock); 10697420ed23SVenkat Yekkirala sock = NULL; 10707420ed23SVenkat Yekkirala goto out; 10711da177e4SLinus Torvalds } 1072c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite); 10731da177e4SLinus Torvalds 10741da177e4SLinus Torvalds /* No kernel lock held - perfect */ 10751da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait) 10761da177e4SLinus Torvalds { 10771da177e4SLinus Torvalds struct socket *sock; 10781da177e4SLinus Torvalds 10791da177e4SLinus Torvalds /* 10801da177e4SLinus Torvalds * We can't return errors to poll, so it's either yes or no. 10811da177e4SLinus Torvalds */ 1082b69aee04SEric Dumazet sock = file->private_data; 10831da177e4SLinus Torvalds return sock->ops->poll(file, sock, wait); 10841da177e4SLinus Torvalds } 10851da177e4SLinus Torvalds 10861da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma) 10871da177e4SLinus Torvalds { 1088b69aee04SEric Dumazet struct socket *sock = file->private_data; 10891da177e4SLinus Torvalds 10901da177e4SLinus Torvalds return sock->ops->mmap(file, sock, vma); 10911da177e4SLinus Torvalds } 10921da177e4SLinus Torvalds 109320380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp) 10941da177e4SLinus Torvalds { 10951da177e4SLinus Torvalds /* 10961da177e4SLinus Torvalds * It was possible the inode is NULL we were 10971da177e4SLinus Torvalds * closing an unfinished socket. 10981da177e4SLinus Torvalds */ 10991da177e4SLinus Torvalds 110089bddce5SStephen Hemminger if (!inode) { 11011da177e4SLinus Torvalds printk(KERN_DEBUG "sock_close: NULL inode\n"); 11021da177e4SLinus Torvalds return 0; 11031da177e4SLinus Torvalds } 11041da177e4SLinus Torvalds sock_release(SOCKET_I(inode)); 11051da177e4SLinus Torvalds return 0; 11061da177e4SLinus Torvalds } 11071da177e4SLinus Torvalds 11081da177e4SLinus Torvalds /* 11091da177e4SLinus Torvalds * Update the socket async list 11101da177e4SLinus Torvalds * 11111da177e4SLinus Torvalds * Fasync_list locking strategy. 11121da177e4SLinus Torvalds * 11131da177e4SLinus Torvalds * 1. fasync_list is modified only under process context socket lock 11141da177e4SLinus Torvalds * i.e. under semaphore. 11151da177e4SLinus Torvalds * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1116989a2979SEric Dumazet * or under socket lock 11171da177e4SLinus Torvalds */ 11181da177e4SLinus Torvalds 11191da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on) 11201da177e4SLinus Torvalds { 1121989a2979SEric Dumazet struct socket *sock = filp->private_data; 1122989a2979SEric Dumazet struct sock *sk = sock->sk; 1123eaefd110SEric Dumazet struct socket_wq *wq; 11241da177e4SLinus Torvalds 1125989a2979SEric Dumazet if (sk == NULL) 11261da177e4SLinus Torvalds return -EINVAL; 11271da177e4SLinus Torvalds 11281da177e4SLinus Torvalds lock_sock(sk); 1129eaefd110SEric Dumazet wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk)); 1130eaefd110SEric Dumazet fasync_helper(fd, filp, on, &wq->fasync_list); 11311da177e4SLinus Torvalds 1132eaefd110SEric Dumazet if (!wq->fasync_list) 1133bcdce719SEric Dumazet sock_reset_flag(sk, SOCK_FASYNC); 1134989a2979SEric Dumazet else 1135989a2979SEric Dumazet sock_set_flag(sk, SOCK_FASYNC); 11361da177e4SLinus Torvalds 1137989a2979SEric Dumazet release_sock(sk); 11381da177e4SLinus Torvalds return 0; 11391da177e4SLinus Torvalds } 11401da177e4SLinus Torvalds 114143815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */ 11421da177e4SLinus Torvalds 11431da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band) 11441da177e4SLinus Torvalds { 114543815482SEric Dumazet struct socket_wq *wq; 114643815482SEric Dumazet 114743815482SEric Dumazet if (!sock) 11481da177e4SLinus Torvalds return -1; 114943815482SEric Dumazet rcu_read_lock(); 115043815482SEric Dumazet wq = rcu_dereference(sock->wq); 115143815482SEric Dumazet if (!wq || !wq->fasync_list) { 115243815482SEric Dumazet rcu_read_unlock(); 115343815482SEric Dumazet return -1; 115443815482SEric Dumazet } 115589bddce5SStephen Hemminger switch (how) { 11568d8ad9d7SPavel Emelyanov case SOCK_WAKE_WAITD: 11571da177e4SLinus Torvalds if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) 11581da177e4SLinus Torvalds break; 11591da177e4SLinus Torvalds goto call_kill; 11608d8ad9d7SPavel Emelyanov case SOCK_WAKE_SPACE: 11611da177e4SLinus Torvalds if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags)) 11621da177e4SLinus Torvalds break; 11631da177e4SLinus Torvalds /* fall through */ 11648d8ad9d7SPavel Emelyanov case SOCK_WAKE_IO: 11651da177e4SLinus Torvalds call_kill: 116643815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGIO, band); 11671da177e4SLinus Torvalds break; 11688d8ad9d7SPavel Emelyanov case SOCK_WAKE_URG: 116943815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGURG, band); 11701da177e4SLinus Torvalds } 117143815482SEric Dumazet rcu_read_unlock(); 11721da177e4SLinus Torvalds return 0; 11731da177e4SLinus Torvalds } 1174c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async); 11751da177e4SLinus Torvalds 1176721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol, 117789bddce5SStephen Hemminger struct socket **res, int kern) 11781da177e4SLinus Torvalds { 11791da177e4SLinus Torvalds int err; 11801da177e4SLinus Torvalds struct socket *sock; 118155737fdaSStephen Hemminger const struct net_proto_family *pf; 11821da177e4SLinus Torvalds 11831da177e4SLinus Torvalds /* 11841da177e4SLinus Torvalds * Check protocol is in range 11851da177e4SLinus Torvalds */ 11861da177e4SLinus Torvalds if (family < 0 || family >= NPROTO) 11871da177e4SLinus Torvalds return -EAFNOSUPPORT; 11881da177e4SLinus Torvalds if (type < 0 || type >= SOCK_MAX) 11891da177e4SLinus Torvalds return -EINVAL; 11901da177e4SLinus Torvalds 11911da177e4SLinus Torvalds /* Compatibility. 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds This uglymoron is moved from INET layer to here to avoid 11941da177e4SLinus Torvalds deadlock in module load. 11951da177e4SLinus Torvalds */ 11961da177e4SLinus Torvalds if (family == PF_INET && type == SOCK_PACKET) { 11971da177e4SLinus Torvalds static int warned; 11981da177e4SLinus Torvalds if (!warned) { 11991da177e4SLinus Torvalds warned = 1; 120089bddce5SStephen Hemminger printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", 120189bddce5SStephen Hemminger current->comm); 12021da177e4SLinus Torvalds } 12031da177e4SLinus Torvalds family = PF_PACKET; 12041da177e4SLinus Torvalds } 12051da177e4SLinus Torvalds 12061da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, kern); 12071da177e4SLinus Torvalds if (err) 12081da177e4SLinus Torvalds return err; 12091da177e4SLinus Torvalds 121055737fdaSStephen Hemminger /* 121155737fdaSStephen Hemminger * Allocate the socket and allow the family to set things up. if 121255737fdaSStephen Hemminger * the protocol is 0, the family is instructed to select an appropriate 121355737fdaSStephen Hemminger * default. 121455737fdaSStephen Hemminger */ 121555737fdaSStephen Hemminger sock = sock_alloc(); 121655737fdaSStephen Hemminger if (!sock) { 121755737fdaSStephen Hemminger if (net_ratelimit()) 121855737fdaSStephen Hemminger printk(KERN_WARNING "socket: no more sockets\n"); 121955737fdaSStephen Hemminger return -ENFILE; /* Not exactly a match, but its the 122055737fdaSStephen Hemminger closest posix thing */ 122155737fdaSStephen Hemminger } 122255737fdaSStephen Hemminger 122355737fdaSStephen Hemminger sock->type = type; 122455737fdaSStephen Hemminger 122595a5afcaSJohannes Berg #ifdef CONFIG_MODULES 12261da177e4SLinus Torvalds /* Attempt to load a protocol module if the find failed. 12271da177e4SLinus Torvalds * 12281da177e4SLinus Torvalds * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user 12291da177e4SLinus Torvalds * requested real, full-featured networking support upon configuration. 12301da177e4SLinus Torvalds * Otherwise module support will break! 12311da177e4SLinus Torvalds */ 1232190683a9SEric Dumazet if (rcu_access_pointer(net_families[family]) == NULL) 12331da177e4SLinus Torvalds request_module("net-pf-%d", family); 12341da177e4SLinus Torvalds #endif 12351da177e4SLinus Torvalds 123655737fdaSStephen Hemminger rcu_read_lock(); 123755737fdaSStephen Hemminger pf = rcu_dereference(net_families[family]); 12381da177e4SLinus Torvalds err = -EAFNOSUPPORT; 123955737fdaSStephen Hemminger if (!pf) 124055737fdaSStephen Hemminger goto out_release; 12411da177e4SLinus Torvalds 12421da177e4SLinus Torvalds /* 12431da177e4SLinus Torvalds * We will call the ->create function, that possibly is in a loadable 12441da177e4SLinus Torvalds * module, so we have to bump that loadable module refcnt first. 12451da177e4SLinus Torvalds */ 124655737fdaSStephen Hemminger if (!try_module_get(pf->owner)) 12471da177e4SLinus Torvalds goto out_release; 12481da177e4SLinus Torvalds 124955737fdaSStephen Hemminger /* Now protected by module ref count */ 125055737fdaSStephen Hemminger rcu_read_unlock(); 125155737fdaSStephen Hemminger 12523f378b68SEric Paris err = pf->create(net, sock, protocol, kern); 125355737fdaSStephen Hemminger if (err < 0) 12541da177e4SLinus Torvalds goto out_module_put; 1255a79af59eSFrank Filz 12561da177e4SLinus Torvalds /* 12571da177e4SLinus Torvalds * Now to bump the refcnt of the [loadable] module that owns this 12581da177e4SLinus Torvalds * socket at sock_release time we decrement its refcnt. 12591da177e4SLinus Torvalds */ 126055737fdaSStephen Hemminger if (!try_module_get(sock->ops->owner)) 126155737fdaSStephen Hemminger goto out_module_busy; 126255737fdaSStephen Hemminger 12631da177e4SLinus Torvalds /* 12641da177e4SLinus Torvalds * Now that we're done with the ->create function, the [loadable] 12651da177e4SLinus Torvalds * module can have its refcnt decremented 12661da177e4SLinus Torvalds */ 126755737fdaSStephen Hemminger module_put(pf->owner); 12687420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, kern); 12697420ed23SVenkat Yekkirala if (err) 12703b185525SHerbert Xu goto out_sock_release; 127155737fdaSStephen Hemminger *res = sock; 12721da177e4SLinus Torvalds 127355737fdaSStephen Hemminger return 0; 127455737fdaSStephen Hemminger 127555737fdaSStephen Hemminger out_module_busy: 127655737fdaSStephen Hemminger err = -EAFNOSUPPORT; 12771da177e4SLinus Torvalds out_module_put: 127855737fdaSStephen Hemminger sock->ops = NULL; 127955737fdaSStephen Hemminger module_put(pf->owner); 128055737fdaSStephen Hemminger out_sock_release: 12811da177e4SLinus Torvalds sock_release(sock); 128255737fdaSStephen Hemminger return err; 128355737fdaSStephen Hemminger 128455737fdaSStephen Hemminger out_release: 128555737fdaSStephen Hemminger rcu_read_unlock(); 128655737fdaSStephen Hemminger goto out_sock_release; 12871da177e4SLinus Torvalds } 1288721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create); 12891da177e4SLinus Torvalds 12901da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res) 12911da177e4SLinus Torvalds { 12921b8d7ae4SEric W. Biederman return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); 12931da177e4SLinus Torvalds } 1294c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create); 12951da177e4SLinus Torvalds 12961da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res) 12971da177e4SLinus Torvalds { 12981b8d7ae4SEric W. Biederman return __sock_create(&init_net, family, type, protocol, res, 1); 12991da177e4SLinus Torvalds } 1300c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern); 13011da177e4SLinus Torvalds 13023e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) 13031da177e4SLinus Torvalds { 13041da177e4SLinus Torvalds int retval; 13051da177e4SLinus Torvalds struct socket *sock; 1306a677a039SUlrich Drepper int flags; 1307a677a039SUlrich Drepper 1308e38b36f3SUlrich Drepper /* Check the SOCK_* constants for consistency. */ 1309e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); 1310e38b36f3SUlrich Drepper BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); 1311e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); 1312e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); 1313e38b36f3SUlrich Drepper 1314a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 131577d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1316a677a039SUlrich Drepper return -EINVAL; 1317a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13181da177e4SLinus Torvalds 1319aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1320aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1321aaca0bdcSUlrich Drepper 13221da177e4SLinus Torvalds retval = sock_create(family, type, protocol, &sock); 13231da177e4SLinus Torvalds if (retval < 0) 13241da177e4SLinus Torvalds goto out; 13251da177e4SLinus Torvalds 132677d27200SUlrich Drepper retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); 13271da177e4SLinus Torvalds if (retval < 0) 13281da177e4SLinus Torvalds goto out_release; 13291da177e4SLinus Torvalds 13301da177e4SLinus Torvalds out: 13311da177e4SLinus Torvalds /* It may be already another descriptor 8) Not kernel problem. */ 13321da177e4SLinus Torvalds return retval; 13331da177e4SLinus Torvalds 13341da177e4SLinus Torvalds out_release: 13351da177e4SLinus Torvalds sock_release(sock); 13361da177e4SLinus Torvalds return retval; 13371da177e4SLinus Torvalds } 13381da177e4SLinus Torvalds 13391da177e4SLinus Torvalds /* 13401da177e4SLinus Torvalds * Create a pair of connected sockets. 13411da177e4SLinus Torvalds */ 13421da177e4SLinus Torvalds 13433e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, 13443e0fa65fSHeiko Carstens int __user *, usockvec) 13451da177e4SLinus Torvalds { 13461da177e4SLinus Torvalds struct socket *sock1, *sock2; 13471da177e4SLinus Torvalds int fd1, fd2, err; 1348db349509SAl Viro struct file *newfile1, *newfile2; 1349a677a039SUlrich Drepper int flags; 1350a677a039SUlrich Drepper 1351a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 135277d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1353a677a039SUlrich Drepper return -EINVAL; 1354a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13551da177e4SLinus Torvalds 1356aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1357aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1358aaca0bdcSUlrich Drepper 13591da177e4SLinus Torvalds /* 13601da177e4SLinus Torvalds * Obtain the first socket and check if the underlying protocol 13611da177e4SLinus Torvalds * supports the socketpair call. 13621da177e4SLinus Torvalds */ 13631da177e4SLinus Torvalds 13641da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock1); 13651da177e4SLinus Torvalds if (err < 0) 13661da177e4SLinus Torvalds goto out; 13671da177e4SLinus Torvalds 13681da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock2); 13691da177e4SLinus Torvalds if (err < 0) 13701da177e4SLinus Torvalds goto out_release_1; 13711da177e4SLinus Torvalds 13721da177e4SLinus Torvalds err = sock1->ops->socketpair(sock1, sock2); 13731da177e4SLinus Torvalds if (err < 0) 13741da177e4SLinus Torvalds goto out_release_both; 13751da177e4SLinus Torvalds 13767cbe66b6SAl Viro fd1 = sock_alloc_file(sock1, &newfile1, flags); 1377bf3c23d1SDavid S. Miller if (unlikely(fd1 < 0)) { 1378bf3c23d1SDavid S. Miller err = fd1; 13791da177e4SLinus Torvalds goto out_release_both; 1380bf3c23d1SDavid S. Miller } 13811da177e4SLinus Torvalds 13827cbe66b6SAl Viro fd2 = sock_alloc_file(sock2, &newfile2, flags); 1383198de4d7SAl Viro if (unlikely(fd2 < 0)) { 1384198de4d7SAl Viro err = fd2; 1385198de4d7SAl Viro fput(newfile1); 1386198de4d7SAl Viro put_unused_fd(fd1); 1387198de4d7SAl Viro sock_release(sock2); 1388198de4d7SAl Viro goto out; 1389db349509SAl Viro } 1390db349509SAl Viro 1391157cf649SAl Viro audit_fd_pair(fd1, fd2); 1392db349509SAl Viro fd_install(fd1, newfile1); 1393db349509SAl Viro fd_install(fd2, newfile2); 13941da177e4SLinus Torvalds /* fd1 and fd2 may be already another descriptors. 13951da177e4SLinus Torvalds * Not kernel problem. 13961da177e4SLinus Torvalds */ 13971da177e4SLinus Torvalds 13981da177e4SLinus Torvalds err = put_user(fd1, &usockvec[0]); 13991da177e4SLinus Torvalds if (!err) 14001da177e4SLinus Torvalds err = put_user(fd2, &usockvec[1]); 14011da177e4SLinus Torvalds if (!err) 14021da177e4SLinus Torvalds return 0; 14031da177e4SLinus Torvalds 14041da177e4SLinus Torvalds sys_close(fd2); 14051da177e4SLinus Torvalds sys_close(fd1); 14061da177e4SLinus Torvalds return err; 14071da177e4SLinus Torvalds 14081da177e4SLinus Torvalds out_release_both: 14091da177e4SLinus Torvalds sock_release(sock2); 14101da177e4SLinus Torvalds out_release_1: 14111da177e4SLinus Torvalds sock_release(sock1); 14121da177e4SLinus Torvalds out: 14131da177e4SLinus Torvalds return err; 14141da177e4SLinus Torvalds } 14151da177e4SLinus Torvalds 14161da177e4SLinus Torvalds /* 14171da177e4SLinus Torvalds * Bind a name to a socket. Nothing much to do here since it's 14181da177e4SLinus Torvalds * the protocol's responsibility to handle the local address. 14191da177e4SLinus Torvalds * 14201da177e4SLinus Torvalds * We move the socket address to kernel space before we call 14211da177e4SLinus Torvalds * the protocol layer (having also checked the address is ok). 14221da177e4SLinus Torvalds */ 14231da177e4SLinus Torvalds 142420f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) 14251da177e4SLinus Torvalds { 14261da177e4SLinus Torvalds struct socket *sock; 1427230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 14286cb153caSBenjamin LaHaise int err, fput_needed; 14291da177e4SLinus Torvalds 143089bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 143189bddce5SStephen Hemminger if (sock) { 1432230b1839SYOSHIFUJI Hideaki err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address); 143389bddce5SStephen Hemminger if (err >= 0) { 143489bddce5SStephen Hemminger err = security_socket_bind(sock, 1435230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 143689bddce5SStephen Hemminger addrlen); 14376cb153caSBenjamin LaHaise if (!err) 14386cb153caSBenjamin LaHaise err = sock->ops->bind(sock, 143989bddce5SStephen Hemminger (struct sockaddr *) 1440230b1839SYOSHIFUJI Hideaki &address, addrlen); 14411da177e4SLinus Torvalds } 14426cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 14431da177e4SLinus Torvalds } 14441da177e4SLinus Torvalds return err; 14451da177e4SLinus Torvalds } 14461da177e4SLinus Torvalds 14471da177e4SLinus Torvalds /* 14481da177e4SLinus Torvalds * Perform a listen. Basically, we allow the protocol to do anything 14491da177e4SLinus Torvalds * necessary for a listen, and if that works, we mark the socket as 14501da177e4SLinus Torvalds * ready for listening. 14511da177e4SLinus Torvalds */ 14521da177e4SLinus Torvalds 14533e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog) 14541da177e4SLinus Torvalds { 14551da177e4SLinus Torvalds struct socket *sock; 14566cb153caSBenjamin LaHaise int err, fput_needed; 1457b8e1f9b5SPavel Emelyanov int somaxconn; 14581da177e4SLinus Torvalds 145989bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 146089bddce5SStephen Hemminger if (sock) { 14618efa6e93SPavel Emelyanov somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 1462b8e1f9b5SPavel Emelyanov if ((unsigned)backlog > somaxconn) 1463b8e1f9b5SPavel Emelyanov backlog = somaxconn; 14641da177e4SLinus Torvalds 14651da177e4SLinus Torvalds err = security_socket_listen(sock, backlog); 14666cb153caSBenjamin LaHaise if (!err) 14671da177e4SLinus Torvalds err = sock->ops->listen(sock, backlog); 14686cb153caSBenjamin LaHaise 14696cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 14701da177e4SLinus Torvalds } 14711da177e4SLinus Torvalds return err; 14721da177e4SLinus Torvalds } 14731da177e4SLinus Torvalds 14741da177e4SLinus Torvalds /* 14751da177e4SLinus Torvalds * For accept, we attempt to create a new socket, set up the link 14761da177e4SLinus Torvalds * with the client, wake up the client, then return the new 14771da177e4SLinus Torvalds * connected fd. We collect the address of the connector in kernel 14781da177e4SLinus Torvalds * space and move it to user at the very end. This is unclean because 14791da177e4SLinus Torvalds * we open the socket then return an error. 14801da177e4SLinus Torvalds * 14811da177e4SLinus Torvalds * 1003.1g adds the ability to recvmsg() to query connection pending 14821da177e4SLinus Torvalds * status to recvmsg. We need to add that support in a way thats 14831da177e4SLinus Torvalds * clean when we restucture accept also. 14841da177e4SLinus Torvalds */ 14851da177e4SLinus Torvalds 148620f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, 148720f37034SHeiko Carstens int __user *, upeer_addrlen, int, flags) 14881da177e4SLinus Torvalds { 14891da177e4SLinus Torvalds struct socket *sock, *newsock; 149039d8c1b6SDavid S. Miller struct file *newfile; 14916cb153caSBenjamin LaHaise int err, len, newfd, fput_needed; 1492230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 14931da177e4SLinus Torvalds 149477d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1495aaca0bdcSUlrich Drepper return -EINVAL; 1496aaca0bdcSUlrich Drepper 1497aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1498aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1499aaca0bdcSUlrich Drepper 15006cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 15011da177e4SLinus Torvalds if (!sock) 15021da177e4SLinus Torvalds goto out; 15031da177e4SLinus Torvalds 15041da177e4SLinus Torvalds err = -ENFILE; 1505c6d409cfSEric Dumazet newsock = sock_alloc(); 1506c6d409cfSEric Dumazet if (!newsock) 15071da177e4SLinus Torvalds goto out_put; 15081da177e4SLinus Torvalds 15091da177e4SLinus Torvalds newsock->type = sock->type; 15101da177e4SLinus Torvalds newsock->ops = sock->ops; 15111da177e4SLinus Torvalds 15121da177e4SLinus Torvalds /* 15131da177e4SLinus Torvalds * We don't need try_module_get here, as the listening socket (sock) 15141da177e4SLinus Torvalds * has the protocol module (sock->ops->owner) held. 15151da177e4SLinus Torvalds */ 15161da177e4SLinus Torvalds __module_get(newsock->ops->owner); 15171da177e4SLinus Torvalds 15187cbe66b6SAl Viro newfd = sock_alloc_file(newsock, &newfile, flags); 151939d8c1b6SDavid S. Miller if (unlikely(newfd < 0)) { 152039d8c1b6SDavid S. Miller err = newfd; 15219a1875e6SDavid S. Miller sock_release(newsock); 15229a1875e6SDavid S. Miller goto out_put; 152339d8c1b6SDavid S. Miller } 152439d8c1b6SDavid S. Miller 1525a79af59eSFrank Filz err = security_socket_accept(sock, newsock); 1526a79af59eSFrank Filz if (err) 152739d8c1b6SDavid S. Miller goto out_fd; 1528a79af59eSFrank Filz 15291da177e4SLinus Torvalds err = sock->ops->accept(sock, newsock, sock->file->f_flags); 15301da177e4SLinus Torvalds if (err < 0) 153139d8c1b6SDavid S. Miller goto out_fd; 15321da177e4SLinus Torvalds 15331da177e4SLinus Torvalds if (upeer_sockaddr) { 1534230b1839SYOSHIFUJI Hideaki if (newsock->ops->getname(newsock, (struct sockaddr *)&address, 153589bddce5SStephen Hemminger &len, 2) < 0) { 15361da177e4SLinus Torvalds err = -ECONNABORTED; 153739d8c1b6SDavid S. Miller goto out_fd; 15381da177e4SLinus Torvalds } 1539230b1839SYOSHIFUJI Hideaki err = move_addr_to_user((struct sockaddr *)&address, 1540230b1839SYOSHIFUJI Hideaki len, upeer_sockaddr, upeer_addrlen); 15411da177e4SLinus Torvalds if (err < 0) 154239d8c1b6SDavid S. Miller goto out_fd; 15431da177e4SLinus Torvalds } 15441da177e4SLinus Torvalds 15451da177e4SLinus Torvalds /* File flags are not inherited via accept() unlike another OSes. */ 15461da177e4SLinus Torvalds 154739d8c1b6SDavid S. Miller fd_install(newfd, newfile); 154839d8c1b6SDavid S. Miller err = newfd; 15491da177e4SLinus Torvalds 15501da177e4SLinus Torvalds out_put: 15516cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 15521da177e4SLinus Torvalds out: 15531da177e4SLinus Torvalds return err; 155439d8c1b6SDavid S. Miller out_fd: 15559606a216SDavid S. Miller fput(newfile); 155639d8c1b6SDavid S. Miller put_unused_fd(newfd); 15571da177e4SLinus Torvalds goto out_put; 15581da177e4SLinus Torvalds } 15591da177e4SLinus Torvalds 156020f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, 156120f37034SHeiko Carstens int __user *, upeer_addrlen) 1562aaca0bdcSUlrich Drepper { 1563de11defeSUlrich Drepper return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); 1564aaca0bdcSUlrich Drepper } 1565aaca0bdcSUlrich Drepper 15661da177e4SLinus Torvalds /* 15671da177e4SLinus Torvalds * Attempt to connect to a socket with the server address. The address 15681da177e4SLinus Torvalds * is in user space so we verify it is OK and move it to kernel space. 15691da177e4SLinus Torvalds * 15701da177e4SLinus Torvalds * For 1003.1g we need to add clean support for a bind to AF_UNSPEC to 15711da177e4SLinus Torvalds * break bindings 15721da177e4SLinus Torvalds * 15731da177e4SLinus Torvalds * NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and 15741da177e4SLinus Torvalds * other SEQPACKET protocols that take time to connect() as it doesn't 15751da177e4SLinus Torvalds * include the -EINPROGRESS status for such sockets. 15761da177e4SLinus Torvalds */ 15771da177e4SLinus Torvalds 157820f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, 157920f37034SHeiko Carstens int, addrlen) 15801da177e4SLinus Torvalds { 15811da177e4SLinus Torvalds struct socket *sock; 1582230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 15836cb153caSBenjamin LaHaise int err, fput_needed; 15841da177e4SLinus Torvalds 15856cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 15861da177e4SLinus Torvalds if (!sock) 15871da177e4SLinus Torvalds goto out; 1588230b1839SYOSHIFUJI Hideaki err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address); 15891da177e4SLinus Torvalds if (err < 0) 15901da177e4SLinus Torvalds goto out_put; 15911da177e4SLinus Torvalds 159289bddce5SStephen Hemminger err = 1593230b1839SYOSHIFUJI Hideaki security_socket_connect(sock, (struct sockaddr *)&address, addrlen); 15941da177e4SLinus Torvalds if (err) 15951da177e4SLinus Torvalds goto out_put; 15961da177e4SLinus Torvalds 1597230b1839SYOSHIFUJI Hideaki err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, 15981da177e4SLinus Torvalds sock->file->f_flags); 15991da177e4SLinus Torvalds out_put: 16006cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16011da177e4SLinus Torvalds out: 16021da177e4SLinus Torvalds return err; 16031da177e4SLinus Torvalds } 16041da177e4SLinus Torvalds 16051da177e4SLinus Torvalds /* 16061da177e4SLinus Torvalds * Get the local address ('name') of a socket object. Move the obtained 16071da177e4SLinus Torvalds * name to user space. 16081da177e4SLinus Torvalds */ 16091da177e4SLinus Torvalds 161020f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr, 161120f37034SHeiko Carstens int __user *, usockaddr_len) 16121da177e4SLinus Torvalds { 16131da177e4SLinus Torvalds struct socket *sock; 1614230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16156cb153caSBenjamin LaHaise int len, err, fput_needed; 16161da177e4SLinus Torvalds 16176cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16181da177e4SLinus Torvalds if (!sock) 16191da177e4SLinus Torvalds goto out; 16201da177e4SLinus Torvalds 16211da177e4SLinus Torvalds err = security_socket_getsockname(sock); 16221da177e4SLinus Torvalds if (err) 16231da177e4SLinus Torvalds goto out_put; 16241da177e4SLinus Torvalds 1625230b1839SYOSHIFUJI Hideaki err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0); 16261da177e4SLinus Torvalds if (err) 16271da177e4SLinus Torvalds goto out_put; 1628230b1839SYOSHIFUJI Hideaki err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len); 16291da177e4SLinus Torvalds 16301da177e4SLinus Torvalds out_put: 16316cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16321da177e4SLinus Torvalds out: 16331da177e4SLinus Torvalds return err; 16341da177e4SLinus Torvalds } 16351da177e4SLinus Torvalds 16361da177e4SLinus Torvalds /* 16371da177e4SLinus Torvalds * Get the remote address ('name') of a socket object. Move the obtained 16381da177e4SLinus Torvalds * name to user space. 16391da177e4SLinus Torvalds */ 16401da177e4SLinus Torvalds 164120f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, 164220f37034SHeiko Carstens int __user *, usockaddr_len) 16431da177e4SLinus Torvalds { 16441da177e4SLinus Torvalds struct socket *sock; 1645230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16466cb153caSBenjamin LaHaise int len, err, fput_needed; 16471da177e4SLinus Torvalds 164889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 164989bddce5SStephen Hemminger if (sock != NULL) { 16501da177e4SLinus Torvalds err = security_socket_getpeername(sock); 16511da177e4SLinus Torvalds if (err) { 16526cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16531da177e4SLinus Torvalds return err; 16541da177e4SLinus Torvalds } 16551da177e4SLinus Torvalds 165689bddce5SStephen Hemminger err = 1657230b1839SYOSHIFUJI Hideaki sock->ops->getname(sock, (struct sockaddr *)&address, &len, 165889bddce5SStephen Hemminger 1); 16591da177e4SLinus Torvalds if (!err) 1660230b1839SYOSHIFUJI Hideaki err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, 166189bddce5SStephen Hemminger usockaddr_len); 16626cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16631da177e4SLinus Torvalds } 16641da177e4SLinus Torvalds return err; 16651da177e4SLinus Torvalds } 16661da177e4SLinus Torvalds 16671da177e4SLinus Torvalds /* 16681da177e4SLinus Torvalds * Send a datagram to a given address. We move the address into kernel 16691da177e4SLinus Torvalds * space and check the user space data area is readable before invoking 16701da177e4SLinus Torvalds * the protocol. 16711da177e4SLinus Torvalds */ 16721da177e4SLinus Torvalds 16733e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, 16743e0fa65fSHeiko Carstens unsigned, flags, struct sockaddr __user *, addr, 16753e0fa65fSHeiko Carstens int, addr_len) 16761da177e4SLinus Torvalds { 16771da177e4SLinus Torvalds struct socket *sock; 1678230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16791da177e4SLinus Torvalds int err; 16801da177e4SLinus Torvalds struct msghdr msg; 16811da177e4SLinus Torvalds struct iovec iov; 16826cb153caSBenjamin LaHaise int fput_needed; 16831da177e4SLinus Torvalds 1684253eacc0SLinus Torvalds if (len > INT_MAX) 1685253eacc0SLinus Torvalds len = INT_MAX; 1686de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 1687de0fa95cSPavel Emelyanov if (!sock) 16884387ff75SDavid S. Miller goto out; 16896cb153caSBenjamin LaHaise 16901da177e4SLinus Torvalds iov.iov_base = buff; 16911da177e4SLinus Torvalds iov.iov_len = len; 16921da177e4SLinus Torvalds msg.msg_name = NULL; 16931da177e4SLinus Torvalds msg.msg_iov = &iov; 16941da177e4SLinus Torvalds msg.msg_iovlen = 1; 16951da177e4SLinus Torvalds msg.msg_control = NULL; 16961da177e4SLinus Torvalds msg.msg_controllen = 0; 16971da177e4SLinus Torvalds msg.msg_namelen = 0; 16986cb153caSBenjamin LaHaise if (addr) { 1699230b1839SYOSHIFUJI Hideaki err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address); 17001da177e4SLinus Torvalds if (err < 0) 17011da177e4SLinus Torvalds goto out_put; 1702230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 17031da177e4SLinus Torvalds msg.msg_namelen = addr_len; 17041da177e4SLinus Torvalds } 17051da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 17061da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 17071da177e4SLinus Torvalds msg.msg_flags = flags; 17081da177e4SLinus Torvalds err = sock_sendmsg(sock, &msg, len); 17091da177e4SLinus Torvalds 17101da177e4SLinus Torvalds out_put: 1711de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 17124387ff75SDavid S. Miller out: 17131da177e4SLinus Torvalds return err; 17141da177e4SLinus Torvalds } 17151da177e4SLinus Torvalds 17161da177e4SLinus Torvalds /* 17171da177e4SLinus Torvalds * Send a datagram down a socket. 17181da177e4SLinus Torvalds */ 17191da177e4SLinus Torvalds 17203e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, 17213e0fa65fSHeiko Carstens unsigned, flags) 17221da177e4SLinus Torvalds { 17231da177e4SLinus Torvalds return sys_sendto(fd, buff, len, flags, NULL, 0); 17241da177e4SLinus Torvalds } 17251da177e4SLinus Torvalds 17261da177e4SLinus Torvalds /* 17271da177e4SLinus Torvalds * Receive a frame from the socket and optionally record the address of the 17281da177e4SLinus Torvalds * sender. We verify the buffers are writable and if needed move the 17291da177e4SLinus Torvalds * sender address from kernel to user space. 17301da177e4SLinus Torvalds */ 17311da177e4SLinus Torvalds 17323e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, 17333e0fa65fSHeiko Carstens unsigned, flags, struct sockaddr __user *, addr, 17343e0fa65fSHeiko Carstens int __user *, addr_len) 17351da177e4SLinus Torvalds { 17361da177e4SLinus Torvalds struct socket *sock; 17371da177e4SLinus Torvalds struct iovec iov; 17381da177e4SLinus Torvalds struct msghdr msg; 1739230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17401da177e4SLinus Torvalds int err, err2; 17416cb153caSBenjamin LaHaise int fput_needed; 17421da177e4SLinus Torvalds 1743253eacc0SLinus Torvalds if (size > INT_MAX) 1744253eacc0SLinus Torvalds size = INT_MAX; 1745de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 17461da177e4SLinus Torvalds if (!sock) 1747de0fa95cSPavel Emelyanov goto out; 17481da177e4SLinus Torvalds 17491da177e4SLinus Torvalds msg.msg_control = NULL; 17501da177e4SLinus Torvalds msg.msg_controllen = 0; 17511da177e4SLinus Torvalds msg.msg_iovlen = 1; 17521da177e4SLinus Torvalds msg.msg_iov = &iov; 17531da177e4SLinus Torvalds iov.iov_len = size; 17541da177e4SLinus Torvalds iov.iov_base = ubuf; 1755230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 1756230b1839SYOSHIFUJI Hideaki msg.msg_namelen = sizeof(address); 17571da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 17581da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 17591da177e4SLinus Torvalds err = sock_recvmsg(sock, &msg, size, flags); 17601da177e4SLinus Torvalds 176189bddce5SStephen Hemminger if (err >= 0 && addr != NULL) { 1762230b1839SYOSHIFUJI Hideaki err2 = move_addr_to_user((struct sockaddr *)&address, 1763230b1839SYOSHIFUJI Hideaki msg.msg_namelen, addr, addr_len); 17641da177e4SLinus Torvalds if (err2 < 0) 17651da177e4SLinus Torvalds err = err2; 17661da177e4SLinus Torvalds } 1767de0fa95cSPavel Emelyanov 1768de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 17694387ff75SDavid S. Miller out: 17701da177e4SLinus Torvalds return err; 17711da177e4SLinus Torvalds } 17721da177e4SLinus Torvalds 17731da177e4SLinus Torvalds /* 17741da177e4SLinus Torvalds * Receive a datagram from a socket. 17751da177e4SLinus Torvalds */ 17761da177e4SLinus Torvalds 177789bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size, 177889bddce5SStephen Hemminger unsigned flags) 17791da177e4SLinus Torvalds { 17801da177e4SLinus Torvalds return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); 17811da177e4SLinus Torvalds } 17821da177e4SLinus Torvalds 17831da177e4SLinus Torvalds /* 17841da177e4SLinus Torvalds * Set a socket option. Because we don't know the option lengths we have 17851da177e4SLinus Torvalds * to pass the user mode parameter for the protocols to sort out. 17861da177e4SLinus Torvalds */ 17871da177e4SLinus Torvalds 178820f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, 178920f37034SHeiko Carstens char __user *, optval, int, optlen) 17901da177e4SLinus Torvalds { 17916cb153caSBenjamin LaHaise int err, fput_needed; 17921da177e4SLinus Torvalds struct socket *sock; 17931da177e4SLinus Torvalds 17941da177e4SLinus Torvalds if (optlen < 0) 17951da177e4SLinus Torvalds return -EINVAL; 17961da177e4SLinus Torvalds 179789bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 179889bddce5SStephen Hemminger if (sock != NULL) { 17991da177e4SLinus Torvalds err = security_socket_setsockopt(sock, level, optname); 18006cb153caSBenjamin LaHaise if (err) 18016cb153caSBenjamin LaHaise goto out_put; 18021da177e4SLinus Torvalds 18031da177e4SLinus Torvalds if (level == SOL_SOCKET) 180489bddce5SStephen Hemminger err = 180589bddce5SStephen Hemminger sock_setsockopt(sock, level, optname, optval, 180689bddce5SStephen Hemminger optlen); 18071da177e4SLinus Torvalds else 180889bddce5SStephen Hemminger err = 180989bddce5SStephen Hemminger sock->ops->setsockopt(sock, level, optname, optval, 181089bddce5SStephen Hemminger optlen); 18116cb153caSBenjamin LaHaise out_put: 18126cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18131da177e4SLinus Torvalds } 18141da177e4SLinus Torvalds return err; 18151da177e4SLinus Torvalds } 18161da177e4SLinus Torvalds 18171da177e4SLinus Torvalds /* 18181da177e4SLinus Torvalds * Get a socket option. Because we don't know the option lengths we have 18191da177e4SLinus Torvalds * to pass a user mode parameter for the protocols to sort out. 18201da177e4SLinus Torvalds */ 18211da177e4SLinus Torvalds 182220f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, 182320f37034SHeiko Carstens char __user *, optval, int __user *, optlen) 18241da177e4SLinus Torvalds { 18256cb153caSBenjamin LaHaise int err, fput_needed; 18261da177e4SLinus Torvalds struct socket *sock; 18271da177e4SLinus Torvalds 182889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 182989bddce5SStephen Hemminger if (sock != NULL) { 18306cb153caSBenjamin LaHaise err = security_socket_getsockopt(sock, level, optname); 18316cb153caSBenjamin LaHaise if (err) 18326cb153caSBenjamin LaHaise goto out_put; 18331da177e4SLinus Torvalds 18341da177e4SLinus Torvalds if (level == SOL_SOCKET) 183589bddce5SStephen Hemminger err = 183689bddce5SStephen Hemminger sock_getsockopt(sock, level, optname, optval, 183789bddce5SStephen Hemminger optlen); 18381da177e4SLinus Torvalds else 183989bddce5SStephen Hemminger err = 184089bddce5SStephen Hemminger sock->ops->getsockopt(sock, level, optname, optval, 184189bddce5SStephen Hemminger optlen); 18426cb153caSBenjamin LaHaise out_put: 18436cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18441da177e4SLinus Torvalds } 18451da177e4SLinus Torvalds return err; 18461da177e4SLinus Torvalds } 18471da177e4SLinus Torvalds 18481da177e4SLinus Torvalds /* 18491da177e4SLinus Torvalds * Shutdown a socket. 18501da177e4SLinus Torvalds */ 18511da177e4SLinus Torvalds 1852754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how) 18531da177e4SLinus Torvalds { 18546cb153caSBenjamin LaHaise int err, fput_needed; 18551da177e4SLinus Torvalds struct socket *sock; 18561da177e4SLinus Torvalds 185789bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 185889bddce5SStephen Hemminger if (sock != NULL) { 18591da177e4SLinus Torvalds err = security_socket_shutdown(sock, how); 18606cb153caSBenjamin LaHaise if (!err) 18611da177e4SLinus Torvalds err = sock->ops->shutdown(sock, how); 18626cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18631da177e4SLinus Torvalds } 18641da177e4SLinus Torvalds return err; 18651da177e4SLinus Torvalds } 18661da177e4SLinus Torvalds 18671da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit 18681da177e4SLinus Torvalds * fields which are the same type (int / unsigned) on our platforms. 18691da177e4SLinus Torvalds */ 18701da177e4SLinus Torvalds #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) 18711da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) 18721da177e4SLinus Torvalds #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) 18731da177e4SLinus Torvalds 1874228e548eSAnton Blanchard static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, 1875228e548eSAnton Blanchard struct msghdr *msg_sys, unsigned flags, int nosec) 18761da177e4SLinus Torvalds { 187789bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 187889bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 1879230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 18801da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 1881b9d717a7SAlex Williamson unsigned char ctl[sizeof(struct cmsghdr) + 20] 1882b9d717a7SAlex Williamson __attribute__ ((aligned(sizeof(__kernel_size_t)))); 1883b9d717a7SAlex Williamson /* 20 is size of ipv6_pktinfo */ 18841da177e4SLinus Torvalds unsigned char *ctl_buf = ctl; 18851da177e4SLinus Torvalds int err, ctl_len, iov_size, total_len; 18861da177e4SLinus Torvalds 18871da177e4SLinus Torvalds err = -EFAULT; 18881da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) { 1889228e548eSAnton Blanchard if (get_compat_msghdr(msg_sys, msg_compat)) 18901da177e4SLinus Torvalds return -EFAULT; 1891228e548eSAnton Blanchard } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) 18921da177e4SLinus Torvalds return -EFAULT; 18931da177e4SLinus Torvalds 18941da177e4SLinus Torvalds /* do not move before msg_sys is valid */ 18951da177e4SLinus Torvalds err = -EMSGSIZE; 1896228e548eSAnton Blanchard if (msg_sys->msg_iovlen > UIO_MAXIOV) 1897228e548eSAnton Blanchard goto out; 18981da177e4SLinus Torvalds 18991da177e4SLinus Torvalds /* Check whether to allocate the iovec area */ 19001da177e4SLinus Torvalds err = -ENOMEM; 1901228e548eSAnton Blanchard iov_size = msg_sys->msg_iovlen * sizeof(struct iovec); 1902228e548eSAnton Blanchard if (msg_sys->msg_iovlen > UIO_FASTIOV) { 19031da177e4SLinus Torvalds iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); 19041da177e4SLinus Torvalds if (!iov) 1905228e548eSAnton Blanchard goto out; 19061da177e4SLinus Torvalds } 19071da177e4SLinus Torvalds 19081da177e4SLinus Torvalds /* This will also move the address data into kernel space */ 19091da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) { 1910228e548eSAnton Blanchard err = verify_compat_iovec(msg_sys, iov, 1911230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 1912230b1839SYOSHIFUJI Hideaki VERIFY_READ); 19131da177e4SLinus Torvalds } else 1914228e548eSAnton Blanchard err = verify_iovec(msg_sys, iov, 1915230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 1916230b1839SYOSHIFUJI Hideaki VERIFY_READ); 19171da177e4SLinus Torvalds if (err < 0) 19181da177e4SLinus Torvalds goto out_freeiov; 19191da177e4SLinus Torvalds total_len = err; 19201da177e4SLinus Torvalds 19211da177e4SLinus Torvalds err = -ENOBUFS; 19221da177e4SLinus Torvalds 1923228e548eSAnton Blanchard if (msg_sys->msg_controllen > INT_MAX) 19241da177e4SLinus Torvalds goto out_freeiov; 1925228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 19261da177e4SLinus Torvalds if ((MSG_CMSG_COMPAT & flags) && ctl_len) { 192789bddce5SStephen Hemminger err = 1928228e548eSAnton Blanchard cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, 192989bddce5SStephen Hemminger sizeof(ctl)); 19301da177e4SLinus Torvalds if (err) 19311da177e4SLinus Torvalds goto out_freeiov; 1932228e548eSAnton Blanchard ctl_buf = msg_sys->msg_control; 1933228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 19341da177e4SLinus Torvalds } else if (ctl_len) { 193589bddce5SStephen Hemminger if (ctl_len > sizeof(ctl)) { 19361da177e4SLinus Torvalds ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); 19371da177e4SLinus Torvalds if (ctl_buf == NULL) 19381da177e4SLinus Torvalds goto out_freeiov; 19391da177e4SLinus Torvalds } 19401da177e4SLinus Torvalds err = -EFAULT; 19411da177e4SLinus Torvalds /* 1942228e548eSAnton Blanchard * Careful! Before this, msg_sys->msg_control contains a user pointer. 19431da177e4SLinus Torvalds * Afterwards, it will be a kernel pointer. Thus the compiler-assisted 19441da177e4SLinus Torvalds * checking falls down on this. 19451da177e4SLinus Torvalds */ 1946fb8621bbSNamhyung Kim if (copy_from_user(ctl_buf, 1947228e548eSAnton Blanchard (void __user __force *)msg_sys->msg_control, 194889bddce5SStephen Hemminger ctl_len)) 19491da177e4SLinus Torvalds goto out_freectl; 1950228e548eSAnton Blanchard msg_sys->msg_control = ctl_buf; 19511da177e4SLinus Torvalds } 1952228e548eSAnton Blanchard msg_sys->msg_flags = flags; 19531da177e4SLinus Torvalds 19541da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 1955228e548eSAnton Blanchard msg_sys->msg_flags |= MSG_DONTWAIT; 1956228e548eSAnton Blanchard err = (nosec ? sock_sendmsg_nosec : sock_sendmsg)(sock, msg_sys, 1957228e548eSAnton Blanchard total_len); 19581da177e4SLinus Torvalds 19591da177e4SLinus Torvalds out_freectl: 19601da177e4SLinus Torvalds if (ctl_buf != ctl) 19611da177e4SLinus Torvalds sock_kfree_s(sock->sk, ctl_buf, ctl_len); 19621da177e4SLinus Torvalds out_freeiov: 19631da177e4SLinus Torvalds if (iov != iovstack) 19641da177e4SLinus Torvalds sock_kfree_s(sock->sk, iov, iov_size); 1965228e548eSAnton Blanchard out: 1966228e548eSAnton Blanchard return err; 1967228e548eSAnton Blanchard } 1968228e548eSAnton Blanchard 1969228e548eSAnton Blanchard /* 1970228e548eSAnton Blanchard * BSD sendmsg interface 1971228e548eSAnton Blanchard */ 1972228e548eSAnton Blanchard 1973228e548eSAnton Blanchard SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) 1974228e548eSAnton Blanchard { 1975228e548eSAnton Blanchard int fput_needed, err; 1976228e548eSAnton Blanchard struct msghdr msg_sys; 1977228e548eSAnton Blanchard struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); 1978228e548eSAnton Blanchard 1979228e548eSAnton Blanchard if (!sock) 1980228e548eSAnton Blanchard goto out; 1981228e548eSAnton Blanchard 1982228e548eSAnton Blanchard err = __sys_sendmsg(sock, msg, &msg_sys, flags, 0); 1983228e548eSAnton Blanchard 19846cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19851da177e4SLinus Torvalds out: 19861da177e4SLinus Torvalds return err; 19871da177e4SLinus Torvalds } 19881da177e4SLinus Torvalds 1989228e548eSAnton Blanchard /* 1990228e548eSAnton Blanchard * Linux sendmmsg interface 1991228e548eSAnton Blanchard */ 1992228e548eSAnton Blanchard 1993228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 1994228e548eSAnton Blanchard unsigned int flags) 1995228e548eSAnton Blanchard { 1996228e548eSAnton Blanchard int fput_needed, err, datagrams; 1997228e548eSAnton Blanchard struct socket *sock; 1998228e548eSAnton Blanchard struct mmsghdr __user *entry; 1999228e548eSAnton Blanchard struct compat_mmsghdr __user *compat_entry; 2000228e548eSAnton Blanchard struct msghdr msg_sys; 2001228e548eSAnton Blanchard 2002228e548eSAnton Blanchard datagrams = 0; 2003228e548eSAnton Blanchard 2004228e548eSAnton Blanchard sock = sockfd_lookup_light(fd, &err, &fput_needed); 2005228e548eSAnton Blanchard if (!sock) 2006228e548eSAnton Blanchard return err; 2007228e548eSAnton Blanchard 2008228e548eSAnton Blanchard err = sock_error(sock->sk); 2009228e548eSAnton Blanchard if (err) 2010228e548eSAnton Blanchard goto out_put; 2011228e548eSAnton Blanchard 2012228e548eSAnton Blanchard entry = mmsg; 2013228e548eSAnton Blanchard compat_entry = (struct compat_mmsghdr __user *)mmsg; 2014228e548eSAnton Blanchard 2015228e548eSAnton Blanchard while (datagrams < vlen) { 2016228e548eSAnton Blanchard /* 2017228e548eSAnton Blanchard * No need to ask LSM for more than the first datagram. 2018228e548eSAnton Blanchard */ 2019228e548eSAnton Blanchard if (MSG_CMSG_COMPAT & flags) { 2020228e548eSAnton Blanchard err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, 2021228e548eSAnton Blanchard &msg_sys, flags, datagrams); 2022228e548eSAnton Blanchard if (err < 0) 2023228e548eSAnton Blanchard break; 2024228e548eSAnton Blanchard err = __put_user(err, &compat_entry->msg_len); 2025228e548eSAnton Blanchard ++compat_entry; 2026228e548eSAnton Blanchard } else { 2027228e548eSAnton Blanchard err = __sys_sendmsg(sock, (struct msghdr __user *)entry, 2028228e548eSAnton Blanchard &msg_sys, flags, datagrams); 2029228e548eSAnton Blanchard if (err < 0) 2030228e548eSAnton Blanchard break; 2031228e548eSAnton Blanchard err = put_user(err, &entry->msg_len); 2032228e548eSAnton Blanchard ++entry; 2033228e548eSAnton Blanchard } 2034228e548eSAnton Blanchard 2035228e548eSAnton Blanchard if (err) 2036228e548eSAnton Blanchard break; 2037228e548eSAnton Blanchard ++datagrams; 2038228e548eSAnton Blanchard } 2039228e548eSAnton Blanchard 2040228e548eSAnton Blanchard out_put: 2041228e548eSAnton Blanchard fput_light(sock->file, fput_needed); 2042228e548eSAnton Blanchard 2043228e548eSAnton Blanchard if (err == 0) 2044228e548eSAnton Blanchard return datagrams; 2045228e548eSAnton Blanchard 2046228e548eSAnton Blanchard if (datagrams != 0) { 2047228e548eSAnton Blanchard /* 2048228e548eSAnton Blanchard * We may send less entries than requested (vlen) if the 2049228e548eSAnton Blanchard * sock is non blocking... 2050228e548eSAnton Blanchard */ 2051228e548eSAnton Blanchard if (err != -EAGAIN) { 2052228e548eSAnton Blanchard /* 2053228e548eSAnton Blanchard * ... or if sendmsg returns an error after we 2054228e548eSAnton Blanchard * send some datagrams, where we record the 2055228e548eSAnton Blanchard * error to return on the next call or if the 2056228e548eSAnton Blanchard * app asks about it using getsockopt(SO_ERROR). 2057228e548eSAnton Blanchard */ 2058228e548eSAnton Blanchard sock->sk->sk_err = -err; 2059228e548eSAnton Blanchard } 2060228e548eSAnton Blanchard 2061228e548eSAnton Blanchard return datagrams; 2062228e548eSAnton Blanchard } 2063228e548eSAnton Blanchard 2064228e548eSAnton Blanchard return err; 2065228e548eSAnton Blanchard } 2066228e548eSAnton Blanchard 2067228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, 2068228e548eSAnton Blanchard unsigned int, vlen, unsigned int, flags) 2069228e548eSAnton Blanchard { 2070228e548eSAnton Blanchard return __sys_sendmmsg(fd, mmsg, vlen, flags); 2071228e548eSAnton Blanchard } 2072228e548eSAnton Blanchard 2073a2e27255SArnaldo Carvalho de Melo static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, 2074a2e27255SArnaldo Carvalho de Melo struct msghdr *msg_sys, unsigned flags, int nosec) 20751da177e4SLinus Torvalds { 207689bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 207789bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 20781da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV]; 20791da177e4SLinus Torvalds struct iovec *iov = iovstack; 20801da177e4SLinus Torvalds unsigned long cmsg_ptr; 20811da177e4SLinus Torvalds int err, iov_size, total_len, len; 20821da177e4SLinus Torvalds 20831da177e4SLinus Torvalds /* kernel mode address */ 2084230b1839SYOSHIFUJI Hideaki struct sockaddr_storage addr; 20851da177e4SLinus Torvalds 20861da177e4SLinus Torvalds /* user mode address pointers */ 20871da177e4SLinus Torvalds struct sockaddr __user *uaddr; 20881da177e4SLinus Torvalds int __user *uaddr_len; 20891da177e4SLinus Torvalds 20901da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) { 2091a2e27255SArnaldo Carvalho de Melo if (get_compat_msghdr(msg_sys, msg_compat)) 20921da177e4SLinus Torvalds return -EFAULT; 2093c6d409cfSEric Dumazet } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) 20941da177e4SLinus Torvalds return -EFAULT; 20951da177e4SLinus Torvalds 20961da177e4SLinus Torvalds err = -EMSGSIZE; 2097a2e27255SArnaldo Carvalho de Melo if (msg_sys->msg_iovlen > UIO_MAXIOV) 2098a2e27255SArnaldo Carvalho de Melo goto out; 20991da177e4SLinus Torvalds 21001da177e4SLinus Torvalds /* Check whether to allocate the iovec area */ 21011da177e4SLinus Torvalds err = -ENOMEM; 2102a2e27255SArnaldo Carvalho de Melo iov_size = msg_sys->msg_iovlen * sizeof(struct iovec); 2103a2e27255SArnaldo Carvalho de Melo if (msg_sys->msg_iovlen > UIO_FASTIOV) { 21041da177e4SLinus Torvalds iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); 21051da177e4SLinus Torvalds if (!iov) 2106a2e27255SArnaldo Carvalho de Melo goto out; 21071da177e4SLinus Torvalds } 21081da177e4SLinus Torvalds 21091da177e4SLinus Torvalds /* 21101da177e4SLinus Torvalds * Save the user-mode address (verify_iovec will change the 21111da177e4SLinus Torvalds * kernel msghdr to use the kernel address space) 21121da177e4SLinus Torvalds */ 21131da177e4SLinus Torvalds 2114a2e27255SArnaldo Carvalho de Melo uaddr = (__force void __user *)msg_sys->msg_name; 21151da177e4SLinus Torvalds uaddr_len = COMPAT_NAMELEN(msg); 21161da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) { 2117a2e27255SArnaldo Carvalho de Melo err = verify_compat_iovec(msg_sys, iov, 2118230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&addr, 2119230b1839SYOSHIFUJI Hideaki VERIFY_WRITE); 21201da177e4SLinus Torvalds } else 2121a2e27255SArnaldo Carvalho de Melo err = verify_iovec(msg_sys, iov, 2122230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&addr, 2123230b1839SYOSHIFUJI Hideaki VERIFY_WRITE); 21241da177e4SLinus Torvalds if (err < 0) 21251da177e4SLinus Torvalds goto out_freeiov; 21261da177e4SLinus Torvalds total_len = err; 21271da177e4SLinus Torvalds 2128a2e27255SArnaldo Carvalho de Melo cmsg_ptr = (unsigned long)msg_sys->msg_control; 2129a2e27255SArnaldo Carvalho de Melo msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 21301da177e4SLinus Torvalds 21311da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 21321da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 2133a2e27255SArnaldo Carvalho de Melo err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, 2134a2e27255SArnaldo Carvalho de Melo total_len, flags); 21351da177e4SLinus Torvalds if (err < 0) 21361da177e4SLinus Torvalds goto out_freeiov; 21371da177e4SLinus Torvalds len = err; 21381da177e4SLinus Torvalds 21391da177e4SLinus Torvalds if (uaddr != NULL) { 2140230b1839SYOSHIFUJI Hideaki err = move_addr_to_user((struct sockaddr *)&addr, 2141a2e27255SArnaldo Carvalho de Melo msg_sys->msg_namelen, uaddr, 214289bddce5SStephen Hemminger uaddr_len); 21431da177e4SLinus Torvalds if (err < 0) 21441da177e4SLinus Torvalds goto out_freeiov; 21451da177e4SLinus Torvalds } 2146a2e27255SArnaldo Carvalho de Melo err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT), 214737f7f421SDavid S. Miller COMPAT_FLAGS(msg)); 21481da177e4SLinus Torvalds if (err) 21491da177e4SLinus Torvalds goto out_freeiov; 21501da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) 2151a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 21521da177e4SLinus Torvalds &msg_compat->msg_controllen); 21531da177e4SLinus Torvalds else 2154a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 21551da177e4SLinus Torvalds &msg->msg_controllen); 21561da177e4SLinus Torvalds if (err) 21571da177e4SLinus Torvalds goto out_freeiov; 21581da177e4SLinus Torvalds err = len; 21591da177e4SLinus Torvalds 21601da177e4SLinus Torvalds out_freeiov: 21611da177e4SLinus Torvalds if (iov != iovstack) 21621da177e4SLinus Torvalds sock_kfree_s(sock->sk, iov, iov_size); 2163a2e27255SArnaldo Carvalho de Melo out: 2164a2e27255SArnaldo Carvalho de Melo return err; 2165a2e27255SArnaldo Carvalho de Melo } 2166a2e27255SArnaldo Carvalho de Melo 2167a2e27255SArnaldo Carvalho de Melo /* 2168a2e27255SArnaldo Carvalho de Melo * BSD recvmsg interface 2169a2e27255SArnaldo Carvalho de Melo */ 2170a2e27255SArnaldo Carvalho de Melo 2171a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, 2172a2e27255SArnaldo Carvalho de Melo unsigned int, flags) 2173a2e27255SArnaldo Carvalho de Melo { 2174a2e27255SArnaldo Carvalho de Melo int fput_needed, err; 2175a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2176a2e27255SArnaldo Carvalho de Melo struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); 2177a2e27255SArnaldo Carvalho de Melo 2178a2e27255SArnaldo Carvalho de Melo if (!sock) 2179a2e27255SArnaldo Carvalho de Melo goto out; 2180a2e27255SArnaldo Carvalho de Melo 2181a2e27255SArnaldo Carvalho de Melo err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2182a2e27255SArnaldo Carvalho de Melo 21836cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 21841da177e4SLinus Torvalds out: 21851da177e4SLinus Torvalds return err; 21861da177e4SLinus Torvalds } 21871da177e4SLinus Torvalds 2188a2e27255SArnaldo Carvalho de Melo /* 2189a2e27255SArnaldo Carvalho de Melo * Linux recvmmsg interface 2190a2e27255SArnaldo Carvalho de Melo */ 21911da177e4SLinus Torvalds 2192a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2193a2e27255SArnaldo Carvalho de Melo unsigned int flags, struct timespec *timeout) 2194a2e27255SArnaldo Carvalho de Melo { 2195a2e27255SArnaldo Carvalho de Melo int fput_needed, err, datagrams; 2196a2e27255SArnaldo Carvalho de Melo struct socket *sock; 2197a2e27255SArnaldo Carvalho de Melo struct mmsghdr __user *entry; 2198d7256d0eSJean-Mickael Guerin struct compat_mmsghdr __user *compat_entry; 2199a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2200a2e27255SArnaldo Carvalho de Melo struct timespec end_time; 2201a2e27255SArnaldo Carvalho de Melo 2202a2e27255SArnaldo Carvalho de Melo if (timeout && 2203a2e27255SArnaldo Carvalho de Melo poll_select_set_timeout(&end_time, timeout->tv_sec, 2204a2e27255SArnaldo Carvalho de Melo timeout->tv_nsec)) 2205a2e27255SArnaldo Carvalho de Melo return -EINVAL; 2206a2e27255SArnaldo Carvalho de Melo 2207a2e27255SArnaldo Carvalho de Melo datagrams = 0; 2208a2e27255SArnaldo Carvalho de Melo 2209a2e27255SArnaldo Carvalho de Melo sock = sockfd_lookup_light(fd, &err, &fput_needed); 2210a2e27255SArnaldo Carvalho de Melo if (!sock) 2211a2e27255SArnaldo Carvalho de Melo return err; 2212a2e27255SArnaldo Carvalho de Melo 2213a2e27255SArnaldo Carvalho de Melo err = sock_error(sock->sk); 2214a2e27255SArnaldo Carvalho de Melo if (err) 2215a2e27255SArnaldo Carvalho de Melo goto out_put; 2216a2e27255SArnaldo Carvalho de Melo 2217a2e27255SArnaldo Carvalho de Melo entry = mmsg; 2218d7256d0eSJean-Mickael Guerin compat_entry = (struct compat_mmsghdr __user *)mmsg; 2219a2e27255SArnaldo Carvalho de Melo 2220a2e27255SArnaldo Carvalho de Melo while (datagrams < vlen) { 2221a2e27255SArnaldo Carvalho de Melo /* 2222a2e27255SArnaldo Carvalho de Melo * No need to ask LSM for more than the first datagram. 2223a2e27255SArnaldo Carvalho de Melo */ 2224d7256d0eSJean-Mickael Guerin if (MSG_CMSG_COMPAT & flags) { 2225d7256d0eSJean-Mickael Guerin err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry, 2226b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2227b9eb8b87SAnton Blanchard datagrams); 2228d7256d0eSJean-Mickael Guerin if (err < 0) 2229d7256d0eSJean-Mickael Guerin break; 2230d7256d0eSJean-Mickael Guerin err = __put_user(err, &compat_entry->msg_len); 2231d7256d0eSJean-Mickael Guerin ++compat_entry; 2232d7256d0eSJean-Mickael Guerin } else { 2233a2e27255SArnaldo Carvalho de Melo err = __sys_recvmsg(sock, (struct msghdr __user *)entry, 2234b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2235b9eb8b87SAnton Blanchard datagrams); 2236a2e27255SArnaldo Carvalho de Melo if (err < 0) 2237a2e27255SArnaldo Carvalho de Melo break; 2238a2e27255SArnaldo Carvalho de Melo err = put_user(err, &entry->msg_len); 2239d7256d0eSJean-Mickael Guerin ++entry; 2240d7256d0eSJean-Mickael Guerin } 2241d7256d0eSJean-Mickael Guerin 2242a2e27255SArnaldo Carvalho de Melo if (err) 2243a2e27255SArnaldo Carvalho de Melo break; 2244a2e27255SArnaldo Carvalho de Melo ++datagrams; 2245a2e27255SArnaldo Carvalho de Melo 224671c5c159SBrandon L Black /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ 224771c5c159SBrandon L Black if (flags & MSG_WAITFORONE) 224871c5c159SBrandon L Black flags |= MSG_DONTWAIT; 224971c5c159SBrandon L Black 2250a2e27255SArnaldo Carvalho de Melo if (timeout) { 2251a2e27255SArnaldo Carvalho de Melo ktime_get_ts(timeout); 2252a2e27255SArnaldo Carvalho de Melo *timeout = timespec_sub(end_time, *timeout); 2253a2e27255SArnaldo Carvalho de Melo if (timeout->tv_sec < 0) { 2254a2e27255SArnaldo Carvalho de Melo timeout->tv_sec = timeout->tv_nsec = 0; 2255a2e27255SArnaldo Carvalho de Melo break; 2256a2e27255SArnaldo Carvalho de Melo } 2257a2e27255SArnaldo Carvalho de Melo 2258a2e27255SArnaldo Carvalho de Melo /* Timeout, return less than vlen datagrams */ 2259a2e27255SArnaldo Carvalho de Melo if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) 2260a2e27255SArnaldo Carvalho de Melo break; 2261a2e27255SArnaldo Carvalho de Melo } 2262a2e27255SArnaldo Carvalho de Melo 2263a2e27255SArnaldo Carvalho de Melo /* Out of band data, return right away */ 2264a2e27255SArnaldo Carvalho de Melo if (msg_sys.msg_flags & MSG_OOB) 2265a2e27255SArnaldo Carvalho de Melo break; 2266a2e27255SArnaldo Carvalho de Melo } 2267a2e27255SArnaldo Carvalho de Melo 2268a2e27255SArnaldo Carvalho de Melo out_put: 2269a2e27255SArnaldo Carvalho de Melo fput_light(sock->file, fput_needed); 2270a2e27255SArnaldo Carvalho de Melo 2271a2e27255SArnaldo Carvalho de Melo if (err == 0) 2272a2e27255SArnaldo Carvalho de Melo return datagrams; 2273a2e27255SArnaldo Carvalho de Melo 2274a2e27255SArnaldo Carvalho de Melo if (datagrams != 0) { 2275a2e27255SArnaldo Carvalho de Melo /* 2276a2e27255SArnaldo Carvalho de Melo * We may return less entries than requested (vlen) if the 2277a2e27255SArnaldo Carvalho de Melo * sock is non block and there aren't enough datagrams... 2278a2e27255SArnaldo Carvalho de Melo */ 2279a2e27255SArnaldo Carvalho de Melo if (err != -EAGAIN) { 2280a2e27255SArnaldo Carvalho de Melo /* 2281a2e27255SArnaldo Carvalho de Melo * ... or if recvmsg returns an error after we 2282a2e27255SArnaldo Carvalho de Melo * received some datagrams, where we record the 2283a2e27255SArnaldo Carvalho de Melo * error to return on the next call or if the 2284a2e27255SArnaldo Carvalho de Melo * app asks about it using getsockopt(SO_ERROR). 2285a2e27255SArnaldo Carvalho de Melo */ 2286a2e27255SArnaldo Carvalho de Melo sock->sk->sk_err = -err; 2287a2e27255SArnaldo Carvalho de Melo } 2288a2e27255SArnaldo Carvalho de Melo 2289a2e27255SArnaldo Carvalho de Melo return datagrams; 2290a2e27255SArnaldo Carvalho de Melo } 2291a2e27255SArnaldo Carvalho de Melo 2292a2e27255SArnaldo Carvalho de Melo return err; 2293a2e27255SArnaldo Carvalho de Melo } 2294a2e27255SArnaldo Carvalho de Melo 2295a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, 2296a2e27255SArnaldo Carvalho de Melo unsigned int, vlen, unsigned int, flags, 2297a2e27255SArnaldo Carvalho de Melo struct timespec __user *, timeout) 2298a2e27255SArnaldo Carvalho de Melo { 2299a2e27255SArnaldo Carvalho de Melo int datagrams; 2300a2e27255SArnaldo Carvalho de Melo struct timespec timeout_sys; 2301a2e27255SArnaldo Carvalho de Melo 2302a2e27255SArnaldo Carvalho de Melo if (!timeout) 2303a2e27255SArnaldo Carvalho de Melo return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); 2304a2e27255SArnaldo Carvalho de Melo 2305a2e27255SArnaldo Carvalho de Melo if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys))) 2306a2e27255SArnaldo Carvalho de Melo return -EFAULT; 2307a2e27255SArnaldo Carvalho de Melo 2308a2e27255SArnaldo Carvalho de Melo datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys); 2309a2e27255SArnaldo Carvalho de Melo 2310a2e27255SArnaldo Carvalho de Melo if (datagrams > 0 && 2311a2e27255SArnaldo Carvalho de Melo copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys))) 2312a2e27255SArnaldo Carvalho de Melo datagrams = -EFAULT; 2313a2e27255SArnaldo Carvalho de Melo 2314a2e27255SArnaldo Carvalho de Melo return datagrams; 2315a2e27255SArnaldo Carvalho de Melo } 2316a2e27255SArnaldo Carvalho de Melo 2317a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL 23181da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */ 23191da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long)) 2320228e548eSAnton Blanchard static const unsigned char nargs[21] = { 232189bddce5SStephen Hemminger AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 23221da177e4SLinus Torvalds AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 2323aaca0bdcSUlrich Drepper AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 2324228e548eSAnton Blanchard AL(4), AL(5), AL(4) 232589bddce5SStephen Hemminger }; 232689bddce5SStephen Hemminger 23271da177e4SLinus Torvalds #undef AL 23281da177e4SLinus Torvalds 23291da177e4SLinus Torvalds /* 23301da177e4SLinus Torvalds * System call vectors. 23311da177e4SLinus Torvalds * 23321da177e4SLinus Torvalds * Argument checking cleaned up. Saved 20% in size. 23331da177e4SLinus Torvalds * This function doesn't need to set the kernel lock because 23341da177e4SLinus Torvalds * it is set by the callees. 23351da177e4SLinus Torvalds */ 23361da177e4SLinus Torvalds 23373e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) 23381da177e4SLinus Torvalds { 23391da177e4SLinus Torvalds unsigned long a[6]; 23401da177e4SLinus Torvalds unsigned long a0, a1; 23411da177e4SLinus Torvalds int err; 234247379052SArjan van de Ven unsigned int len; 23431da177e4SLinus Torvalds 2344228e548eSAnton Blanchard if (call < 1 || call > SYS_SENDMMSG) 23451da177e4SLinus Torvalds return -EINVAL; 23461da177e4SLinus Torvalds 234747379052SArjan van de Ven len = nargs[call]; 234847379052SArjan van de Ven if (len > sizeof(a)) 234947379052SArjan van de Ven return -EINVAL; 235047379052SArjan van de Ven 23511da177e4SLinus Torvalds /* copy_from_user should be SMP safe. */ 235247379052SArjan van de Ven if (copy_from_user(a, args, len)) 23531da177e4SLinus Torvalds return -EFAULT; 23541da177e4SLinus Torvalds 2355f3298dc4SAl Viro audit_socketcall(nargs[call] / sizeof(unsigned long), a); 23563ec3b2fbSDavid Woodhouse 23571da177e4SLinus Torvalds a0 = a[0]; 23581da177e4SLinus Torvalds a1 = a[1]; 23591da177e4SLinus Torvalds 236089bddce5SStephen Hemminger switch (call) { 23611da177e4SLinus Torvalds case SYS_SOCKET: 23621da177e4SLinus Torvalds err = sys_socket(a0, a1, a[2]); 23631da177e4SLinus Torvalds break; 23641da177e4SLinus Torvalds case SYS_BIND: 23651da177e4SLinus Torvalds err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]); 23661da177e4SLinus Torvalds break; 23671da177e4SLinus Torvalds case SYS_CONNECT: 23681da177e4SLinus Torvalds err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]); 23691da177e4SLinus Torvalds break; 23701da177e4SLinus Torvalds case SYS_LISTEN: 23711da177e4SLinus Torvalds err = sys_listen(a0, a1); 23721da177e4SLinus Torvalds break; 23731da177e4SLinus Torvalds case SYS_ACCEPT: 2374de11defeSUlrich Drepper err = sys_accept4(a0, (struct sockaddr __user *)a1, 2375aaca0bdcSUlrich Drepper (int __user *)a[2], 0); 23761da177e4SLinus Torvalds break; 23771da177e4SLinus Torvalds case SYS_GETSOCKNAME: 237889bddce5SStephen Hemminger err = 237989bddce5SStephen Hemminger sys_getsockname(a0, (struct sockaddr __user *)a1, 238089bddce5SStephen Hemminger (int __user *)a[2]); 23811da177e4SLinus Torvalds break; 23821da177e4SLinus Torvalds case SYS_GETPEERNAME: 238389bddce5SStephen Hemminger err = 238489bddce5SStephen Hemminger sys_getpeername(a0, (struct sockaddr __user *)a1, 238589bddce5SStephen Hemminger (int __user *)a[2]); 23861da177e4SLinus Torvalds break; 23871da177e4SLinus Torvalds case SYS_SOCKETPAIR: 23881da177e4SLinus Torvalds err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]); 23891da177e4SLinus Torvalds break; 23901da177e4SLinus Torvalds case SYS_SEND: 23911da177e4SLinus Torvalds err = sys_send(a0, (void __user *)a1, a[2], a[3]); 23921da177e4SLinus Torvalds break; 23931da177e4SLinus Torvalds case SYS_SENDTO: 23941da177e4SLinus Torvalds err = sys_sendto(a0, (void __user *)a1, a[2], a[3], 23951da177e4SLinus Torvalds (struct sockaddr __user *)a[4], a[5]); 23961da177e4SLinus Torvalds break; 23971da177e4SLinus Torvalds case SYS_RECV: 23981da177e4SLinus Torvalds err = sys_recv(a0, (void __user *)a1, a[2], a[3]); 23991da177e4SLinus Torvalds break; 24001da177e4SLinus Torvalds case SYS_RECVFROM: 24011da177e4SLinus Torvalds err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 240289bddce5SStephen Hemminger (struct sockaddr __user *)a[4], 240389bddce5SStephen Hemminger (int __user *)a[5]); 24041da177e4SLinus Torvalds break; 24051da177e4SLinus Torvalds case SYS_SHUTDOWN: 24061da177e4SLinus Torvalds err = sys_shutdown(a0, a1); 24071da177e4SLinus Torvalds break; 24081da177e4SLinus Torvalds case SYS_SETSOCKOPT: 24091da177e4SLinus Torvalds err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]); 24101da177e4SLinus Torvalds break; 24111da177e4SLinus Torvalds case SYS_GETSOCKOPT: 241289bddce5SStephen Hemminger err = 241389bddce5SStephen Hemminger sys_getsockopt(a0, a1, a[2], (char __user *)a[3], 241489bddce5SStephen Hemminger (int __user *)a[4]); 24151da177e4SLinus Torvalds break; 24161da177e4SLinus Torvalds case SYS_SENDMSG: 24171da177e4SLinus Torvalds err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); 24181da177e4SLinus Torvalds break; 2419228e548eSAnton Blanchard case SYS_SENDMMSG: 2420228e548eSAnton Blanchard err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); 2421228e548eSAnton Blanchard break; 24221da177e4SLinus Torvalds case SYS_RECVMSG: 24231da177e4SLinus Torvalds err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); 24241da177e4SLinus Torvalds break; 2425a2e27255SArnaldo Carvalho de Melo case SYS_RECVMMSG: 2426a2e27255SArnaldo Carvalho de Melo err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], 2427a2e27255SArnaldo Carvalho de Melo (struct timespec __user *)a[4]); 2428a2e27255SArnaldo Carvalho de Melo break; 2429de11defeSUlrich Drepper case SYS_ACCEPT4: 2430de11defeSUlrich Drepper err = sys_accept4(a0, (struct sockaddr __user *)a1, 2431de11defeSUlrich Drepper (int __user *)a[2], a[3]); 2432aaca0bdcSUlrich Drepper break; 24331da177e4SLinus Torvalds default: 24341da177e4SLinus Torvalds err = -EINVAL; 24351da177e4SLinus Torvalds break; 24361da177e4SLinus Torvalds } 24371da177e4SLinus Torvalds return err; 24381da177e4SLinus Torvalds } 24391da177e4SLinus Torvalds 24401da177e4SLinus Torvalds #endif /* __ARCH_WANT_SYS_SOCKETCALL */ 24411da177e4SLinus Torvalds 244255737fdaSStephen Hemminger /** 244355737fdaSStephen Hemminger * sock_register - add a socket protocol handler 244455737fdaSStephen Hemminger * @ops: description of protocol 244555737fdaSStephen Hemminger * 24461da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 24471da177e4SLinus Torvalds * advertise its address family, and have it linked into the 244855737fdaSStephen Hemminger * socket interface. The value ops->family coresponds to the 244955737fdaSStephen Hemminger * socket system call protocol family. 24501da177e4SLinus Torvalds */ 2451f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops) 24521da177e4SLinus Torvalds { 24531da177e4SLinus Torvalds int err; 24541da177e4SLinus Torvalds 24551da177e4SLinus Torvalds if (ops->family >= NPROTO) { 245689bddce5SStephen Hemminger printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family, 245789bddce5SStephen Hemminger NPROTO); 24581da177e4SLinus Torvalds return -ENOBUFS; 24591da177e4SLinus Torvalds } 246055737fdaSStephen Hemminger 246155737fdaSStephen Hemminger spin_lock(&net_family_lock); 2462190683a9SEric Dumazet if (rcu_dereference_protected(net_families[ops->family], 2463190683a9SEric Dumazet lockdep_is_held(&net_family_lock))) 24641da177e4SLinus Torvalds err = -EEXIST; 246555737fdaSStephen Hemminger else { 2466190683a9SEric Dumazet rcu_assign_pointer(net_families[ops->family], ops); 24671da177e4SLinus Torvalds err = 0; 24681da177e4SLinus Torvalds } 246955737fdaSStephen Hemminger spin_unlock(&net_family_lock); 247055737fdaSStephen Hemminger 247189bddce5SStephen Hemminger printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family); 24721da177e4SLinus Torvalds return err; 24731da177e4SLinus Torvalds } 2474c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register); 24751da177e4SLinus Torvalds 247655737fdaSStephen Hemminger /** 247755737fdaSStephen Hemminger * sock_unregister - remove a protocol handler 247855737fdaSStephen Hemminger * @family: protocol family to remove 247955737fdaSStephen Hemminger * 24801da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 24811da177e4SLinus Torvalds * remove its address family, and have it unlinked from the 248255737fdaSStephen Hemminger * new socket creation. 248355737fdaSStephen Hemminger * 248455737fdaSStephen Hemminger * If protocol handler is a module, then it can use module reference 248555737fdaSStephen Hemminger * counts to protect against new references. If protocol handler is not 248655737fdaSStephen Hemminger * a module then it needs to provide its own protection in 248755737fdaSStephen Hemminger * the ops->create routine. 24881da177e4SLinus Torvalds */ 2489f0fd27d4SStephen Hemminger void sock_unregister(int family) 24901da177e4SLinus Torvalds { 2491f0fd27d4SStephen Hemminger BUG_ON(family < 0 || family >= NPROTO); 24921da177e4SLinus Torvalds 249355737fdaSStephen Hemminger spin_lock(&net_family_lock); 2494190683a9SEric Dumazet rcu_assign_pointer(net_families[family], NULL); 249555737fdaSStephen Hemminger spin_unlock(&net_family_lock); 249655737fdaSStephen Hemminger 249755737fdaSStephen Hemminger synchronize_rcu(); 249855737fdaSStephen Hemminger 249989bddce5SStephen Hemminger printk(KERN_INFO "NET: Unregistered protocol family %d\n", family); 25001da177e4SLinus Torvalds } 2501c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister); 25021da177e4SLinus Torvalds 250377d76ea3SAndi Kleen static int __init sock_init(void) 25041da177e4SLinus Torvalds { 2505b3e19d92SNick Piggin int err; 2506b3e19d92SNick Piggin 25071da177e4SLinus Torvalds /* 25081da177e4SLinus Torvalds * Initialize sock SLAB cache. 25091da177e4SLinus Torvalds */ 25101da177e4SLinus Torvalds 25111da177e4SLinus Torvalds sk_init(); 25121da177e4SLinus Torvalds 25131da177e4SLinus Torvalds /* 25141da177e4SLinus Torvalds * Initialize skbuff SLAB cache 25151da177e4SLinus Torvalds */ 25161da177e4SLinus Torvalds skb_init(); 25171da177e4SLinus Torvalds 25181da177e4SLinus Torvalds /* 25191da177e4SLinus Torvalds * Initialize the protocols module. 25201da177e4SLinus Torvalds */ 25211da177e4SLinus Torvalds 25221da177e4SLinus Torvalds init_inodecache(); 2523b3e19d92SNick Piggin 2524b3e19d92SNick Piggin err = register_filesystem(&sock_fs_type); 2525b3e19d92SNick Piggin if (err) 2526b3e19d92SNick Piggin goto out_fs; 25271da177e4SLinus Torvalds sock_mnt = kern_mount(&sock_fs_type); 2528b3e19d92SNick Piggin if (IS_ERR(sock_mnt)) { 2529b3e19d92SNick Piggin err = PTR_ERR(sock_mnt); 2530b3e19d92SNick Piggin goto out_mount; 2531b3e19d92SNick Piggin } 253277d76ea3SAndi Kleen 253377d76ea3SAndi Kleen /* The real protocol initialization is performed in later initcalls. 25341da177e4SLinus Torvalds */ 25351da177e4SLinus Torvalds 25361da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER 25371da177e4SLinus Torvalds netfilter_init(); 25381da177e4SLinus Torvalds #endif 2539cbeb321aSDavid S. Miller 2540c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING 2541c1f19b51SRichard Cochran skb_timestamping_init(); 2542c1f19b51SRichard Cochran #endif 2543c1f19b51SRichard Cochran 2544b3e19d92SNick Piggin out: 2545b3e19d92SNick Piggin return err; 2546b3e19d92SNick Piggin 2547b3e19d92SNick Piggin out_mount: 2548b3e19d92SNick Piggin unregister_filesystem(&sock_fs_type); 2549b3e19d92SNick Piggin out_fs: 2550b3e19d92SNick Piggin goto out; 25511da177e4SLinus Torvalds } 25521da177e4SLinus Torvalds 255377d76ea3SAndi Kleen core_initcall(sock_init); /* early initcall */ 255477d76ea3SAndi Kleen 25551da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 25561da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq) 25571da177e4SLinus Torvalds { 25581da177e4SLinus Torvalds int cpu; 25591da177e4SLinus Torvalds int counter = 0; 25601da177e4SLinus Torvalds 25616f912042SKAMEZAWA Hiroyuki for_each_possible_cpu(cpu) 25621da177e4SLinus Torvalds counter += per_cpu(sockets_in_use, cpu); 25631da177e4SLinus Torvalds 25641da177e4SLinus Torvalds /* It can be negative, by the way. 8) */ 25651da177e4SLinus Torvalds if (counter < 0) 25661da177e4SLinus Torvalds counter = 0; 25671da177e4SLinus Torvalds 25681da177e4SLinus Torvalds seq_printf(seq, "sockets: used %d\n", counter); 25691da177e4SLinus Torvalds } 25701da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */ 25711da177e4SLinus Torvalds 257289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 25736b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock, 25746b96018bSArnd Bergmann unsigned int cmd, struct compat_timeval __user *up) 25757a229387SArnd Bergmann { 25767a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 25777a229387SArnd Bergmann struct timeval ktv; 25787a229387SArnd Bergmann int err; 25797a229387SArnd Bergmann 25807a229387SArnd Bergmann set_fs(KERNEL_DS); 25816b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); 25827a229387SArnd Bergmann set_fs(old_fs); 25837a229387SArnd Bergmann if (!err) { 25847a229387SArnd Bergmann err = put_user(ktv.tv_sec, &up->tv_sec); 25857a229387SArnd Bergmann err |= __put_user(ktv.tv_usec, &up->tv_usec); 25867a229387SArnd Bergmann } 25877a229387SArnd Bergmann return err; 25887a229387SArnd Bergmann } 25897a229387SArnd Bergmann 25906b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock, 25916b96018bSArnd Bergmann unsigned int cmd, struct compat_timespec __user *up) 25927a229387SArnd Bergmann { 25937a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 25947a229387SArnd Bergmann struct timespec kts; 25957a229387SArnd Bergmann int err; 25967a229387SArnd Bergmann 25977a229387SArnd Bergmann set_fs(KERNEL_DS); 25986b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); 25997a229387SArnd Bergmann set_fs(old_fs); 26007a229387SArnd Bergmann if (!err) { 26017a229387SArnd Bergmann err = put_user(kts.tv_sec, &up->tv_sec); 26027a229387SArnd Bergmann err |= __put_user(kts.tv_nsec, &up->tv_nsec); 26037a229387SArnd Bergmann } 26047a229387SArnd Bergmann return err; 26057a229387SArnd Bergmann } 26067a229387SArnd Bergmann 26076b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32) 26087a229387SArnd Bergmann { 26097a229387SArnd Bergmann struct ifreq __user *uifr; 26107a229387SArnd Bergmann int err; 26117a229387SArnd Bergmann 26127a229387SArnd Bergmann uifr = compat_alloc_user_space(sizeof(struct ifreq)); 26136b96018bSArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 26147a229387SArnd Bergmann return -EFAULT; 26157a229387SArnd Bergmann 26166b96018bSArnd Bergmann err = dev_ioctl(net, SIOCGIFNAME, uifr); 26177a229387SArnd Bergmann if (err) 26187a229387SArnd Bergmann return err; 26197a229387SArnd Bergmann 26206b96018bSArnd Bergmann if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq))) 26217a229387SArnd Bergmann return -EFAULT; 26227a229387SArnd Bergmann 26237a229387SArnd Bergmann return 0; 26247a229387SArnd Bergmann } 26257a229387SArnd Bergmann 26266b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) 26277a229387SArnd Bergmann { 26286b96018bSArnd Bergmann struct compat_ifconf ifc32; 26297a229387SArnd Bergmann struct ifconf ifc; 26307a229387SArnd Bergmann struct ifconf __user *uifc; 26316b96018bSArnd Bergmann struct compat_ifreq __user *ifr32; 26327a229387SArnd Bergmann struct ifreq __user *ifr; 26337a229387SArnd Bergmann unsigned int i, j; 26347a229387SArnd Bergmann int err; 26357a229387SArnd Bergmann 26366b96018bSArnd Bergmann if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) 26377a229387SArnd Bergmann return -EFAULT; 26387a229387SArnd Bergmann 26397a229387SArnd Bergmann if (ifc32.ifcbuf == 0) { 26407a229387SArnd Bergmann ifc32.ifc_len = 0; 26417a229387SArnd Bergmann ifc.ifc_len = 0; 26427a229387SArnd Bergmann ifc.ifc_req = NULL; 26437a229387SArnd Bergmann uifc = compat_alloc_user_space(sizeof(struct ifconf)); 26447a229387SArnd Bergmann } else { 26456b96018bSArnd Bergmann size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) * 26467a229387SArnd Bergmann sizeof(struct ifreq); 26477a229387SArnd Bergmann uifc = compat_alloc_user_space(sizeof(struct ifconf) + len); 26487a229387SArnd Bergmann ifc.ifc_len = len; 26497a229387SArnd Bergmann ifr = ifc.ifc_req = (void __user *)(uifc + 1); 26507a229387SArnd Bergmann ifr32 = compat_ptr(ifc32.ifcbuf); 26516b96018bSArnd Bergmann for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) { 26526b96018bSArnd Bergmann if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq))) 26537a229387SArnd Bergmann return -EFAULT; 26547a229387SArnd Bergmann ifr++; 26557a229387SArnd Bergmann ifr32++; 26567a229387SArnd Bergmann } 26577a229387SArnd Bergmann } 26587a229387SArnd Bergmann if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) 26597a229387SArnd Bergmann return -EFAULT; 26607a229387SArnd Bergmann 26616b96018bSArnd Bergmann err = dev_ioctl(net, SIOCGIFCONF, uifc); 26627a229387SArnd Bergmann if (err) 26637a229387SArnd Bergmann return err; 26647a229387SArnd Bergmann 26657a229387SArnd Bergmann if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) 26667a229387SArnd Bergmann return -EFAULT; 26677a229387SArnd Bergmann 26687a229387SArnd Bergmann ifr = ifc.ifc_req; 26697a229387SArnd Bergmann ifr32 = compat_ptr(ifc32.ifcbuf); 26707a229387SArnd Bergmann for (i = 0, j = 0; 26716b96018bSArnd Bergmann i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len; 26726b96018bSArnd Bergmann i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) { 26736b96018bSArnd Bergmann if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq))) 26747a229387SArnd Bergmann return -EFAULT; 26757a229387SArnd Bergmann ifr32++; 26767a229387SArnd Bergmann ifr++; 26777a229387SArnd Bergmann } 26787a229387SArnd Bergmann 26797a229387SArnd Bergmann if (ifc32.ifcbuf == 0) { 26807a229387SArnd Bergmann /* Translate from 64-bit structure multiple to 26817a229387SArnd Bergmann * a 32-bit one. 26827a229387SArnd Bergmann */ 26837a229387SArnd Bergmann i = ifc.ifc_len; 26846b96018bSArnd Bergmann i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq)); 26857a229387SArnd Bergmann ifc32.ifc_len = i; 26867a229387SArnd Bergmann } else { 26877a229387SArnd Bergmann ifc32.ifc_len = i; 26887a229387SArnd Bergmann } 26896b96018bSArnd Bergmann if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) 26907a229387SArnd Bergmann return -EFAULT; 26917a229387SArnd Bergmann 26927a229387SArnd Bergmann return 0; 26937a229387SArnd Bergmann } 26947a229387SArnd Bergmann 26956b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) 26967a229387SArnd Bergmann { 26973a7da39dSBen Hutchings struct compat_ethtool_rxnfc __user *compat_rxnfc; 26983a7da39dSBen Hutchings bool convert_in = false, convert_out = false; 26993a7da39dSBen Hutchings size_t buf_size = ALIGN(sizeof(struct ifreq), 8); 27003a7da39dSBen Hutchings struct ethtool_rxnfc __user *rxnfc; 27017a229387SArnd Bergmann struct ifreq __user *ifr; 27023a7da39dSBen Hutchings u32 rule_cnt = 0, actual_rule_cnt; 27033a7da39dSBen Hutchings u32 ethcmd; 27047a229387SArnd Bergmann u32 data; 27053a7da39dSBen Hutchings int ret; 27067a229387SArnd Bergmann 27077a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 27087a229387SArnd Bergmann return -EFAULT; 27097a229387SArnd Bergmann 27103a7da39dSBen Hutchings compat_rxnfc = compat_ptr(data); 27113a7da39dSBen Hutchings 27123a7da39dSBen Hutchings if (get_user(ethcmd, &compat_rxnfc->cmd)) 27137a229387SArnd Bergmann return -EFAULT; 27147a229387SArnd Bergmann 27153a7da39dSBen Hutchings /* Most ethtool structures are defined without padding. 27163a7da39dSBen Hutchings * Unfortunately struct ethtool_rxnfc is an exception. 27173a7da39dSBen Hutchings */ 27183a7da39dSBen Hutchings switch (ethcmd) { 27193a7da39dSBen Hutchings default: 27203a7da39dSBen Hutchings break; 27213a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLALL: 27223a7da39dSBen Hutchings /* Buffer size is variable */ 27233a7da39dSBen Hutchings if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) 27243a7da39dSBen Hutchings return -EFAULT; 27253a7da39dSBen Hutchings if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) 27263a7da39dSBen Hutchings return -ENOMEM; 27273a7da39dSBen Hutchings buf_size += rule_cnt * sizeof(u32); 27283a7da39dSBen Hutchings /* fall through */ 27293a7da39dSBen Hutchings case ETHTOOL_GRXRINGS: 27303a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLCNT: 27313a7da39dSBen Hutchings case ETHTOOL_GRXCLSRULE: 27323a7da39dSBen Hutchings convert_out = true; 27333a7da39dSBen Hutchings /* fall through */ 27343a7da39dSBen Hutchings case ETHTOOL_SRXCLSRLDEL: 27353a7da39dSBen Hutchings case ETHTOOL_SRXCLSRLINS: 27363a7da39dSBen Hutchings buf_size += sizeof(struct ethtool_rxnfc); 27373a7da39dSBen Hutchings convert_in = true; 27383a7da39dSBen Hutchings break; 27393a7da39dSBen Hutchings } 27403a7da39dSBen Hutchings 27413a7da39dSBen Hutchings ifr = compat_alloc_user_space(buf_size); 27423a7da39dSBen Hutchings rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8); 27433a7da39dSBen Hutchings 27443a7da39dSBen Hutchings if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 27453a7da39dSBen Hutchings return -EFAULT; 27463a7da39dSBen Hutchings 27473a7da39dSBen Hutchings if (put_user(convert_in ? rxnfc : compat_ptr(data), 27483a7da39dSBen Hutchings &ifr->ifr_ifru.ifru_data)) 27493a7da39dSBen Hutchings return -EFAULT; 27503a7da39dSBen Hutchings 27513a7da39dSBen Hutchings if (convert_in) { 2752127fe533SAlexander Duyck /* We expect there to be holes between fs.m_ext and 27533a7da39dSBen Hutchings * fs.ring_cookie and at the end of fs, but nowhere else. 27543a7da39dSBen Hutchings */ 2755127fe533SAlexander Duyck BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + 2756127fe533SAlexander Duyck sizeof(compat_rxnfc->fs.m_ext) != 2757127fe533SAlexander Duyck offsetof(struct ethtool_rxnfc, fs.m_ext) + 2758127fe533SAlexander Duyck sizeof(rxnfc->fs.m_ext)); 27593a7da39dSBen Hutchings BUILD_BUG_ON( 27603a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.location) - 27613a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != 27623a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.location) - 27633a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.ring_cookie)); 27643a7da39dSBen Hutchings 27653a7da39dSBen Hutchings if (copy_in_user(rxnfc, compat_rxnfc, 2766127fe533SAlexander Duyck (void *)(&rxnfc->fs.m_ext + 1) - 27673a7da39dSBen Hutchings (void *)rxnfc) || 27683a7da39dSBen Hutchings copy_in_user(&rxnfc->fs.ring_cookie, 27693a7da39dSBen Hutchings &compat_rxnfc->fs.ring_cookie, 27703a7da39dSBen Hutchings (void *)(&rxnfc->fs.location + 1) - 27713a7da39dSBen Hutchings (void *)&rxnfc->fs.ring_cookie) || 27723a7da39dSBen Hutchings copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt, 27733a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 27743a7da39dSBen Hutchings return -EFAULT; 27753a7da39dSBen Hutchings } 27763a7da39dSBen Hutchings 27773a7da39dSBen Hutchings ret = dev_ioctl(net, SIOCETHTOOL, ifr); 27783a7da39dSBen Hutchings if (ret) 27793a7da39dSBen Hutchings return ret; 27803a7da39dSBen Hutchings 27813a7da39dSBen Hutchings if (convert_out) { 27823a7da39dSBen Hutchings if (copy_in_user(compat_rxnfc, rxnfc, 2783127fe533SAlexander Duyck (const void *)(&rxnfc->fs.m_ext + 1) - 27843a7da39dSBen Hutchings (const void *)rxnfc) || 27853a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->fs.ring_cookie, 27863a7da39dSBen Hutchings &rxnfc->fs.ring_cookie, 27873a7da39dSBen Hutchings (const void *)(&rxnfc->fs.location + 1) - 27883a7da39dSBen Hutchings (const void *)&rxnfc->fs.ring_cookie) || 27893a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, 27903a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 27913a7da39dSBen Hutchings return -EFAULT; 27923a7da39dSBen Hutchings 27933a7da39dSBen Hutchings if (ethcmd == ETHTOOL_GRXCLSRLALL) { 27943a7da39dSBen Hutchings /* As an optimisation, we only copy the actual 27953a7da39dSBen Hutchings * number of rules that the underlying 27963a7da39dSBen Hutchings * function returned. Since Mallory might 27973a7da39dSBen Hutchings * change the rule count in user memory, we 27983a7da39dSBen Hutchings * check that it is less than the rule count 27993a7da39dSBen Hutchings * originally given (as the user buffer size), 28003a7da39dSBen Hutchings * which has been range-checked. 28013a7da39dSBen Hutchings */ 28023a7da39dSBen Hutchings if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) 28033a7da39dSBen Hutchings return -EFAULT; 28043a7da39dSBen Hutchings if (actual_rule_cnt < rule_cnt) 28053a7da39dSBen Hutchings rule_cnt = actual_rule_cnt; 28063a7da39dSBen Hutchings if (copy_in_user(&compat_rxnfc->rule_locs[0], 28073a7da39dSBen Hutchings &rxnfc->rule_locs[0], 28083a7da39dSBen Hutchings rule_cnt * sizeof(u32))) 28093a7da39dSBen Hutchings return -EFAULT; 28103a7da39dSBen Hutchings } 28113a7da39dSBen Hutchings } 28123a7da39dSBen Hutchings 28133a7da39dSBen Hutchings return 0; 28147a229387SArnd Bergmann } 28157a229387SArnd Bergmann 28167a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) 28177a50a240SArnd Bergmann { 28187a50a240SArnd Bergmann void __user *uptr; 28197a50a240SArnd Bergmann compat_uptr_t uptr32; 28207a50a240SArnd Bergmann struct ifreq __user *uifr; 28217a50a240SArnd Bergmann 28227a50a240SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 28237a50a240SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 28247a50a240SArnd Bergmann return -EFAULT; 28257a50a240SArnd Bergmann 28267a50a240SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) 28277a50a240SArnd Bergmann return -EFAULT; 28287a50a240SArnd Bergmann 28297a50a240SArnd Bergmann uptr = compat_ptr(uptr32); 28307a50a240SArnd Bergmann 28317a50a240SArnd Bergmann if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc)) 28327a50a240SArnd Bergmann return -EFAULT; 28337a50a240SArnd Bergmann 28347a50a240SArnd Bergmann return dev_ioctl(net, SIOCWANDEV, uifr); 28357a50a240SArnd Bergmann } 28367a50a240SArnd Bergmann 28376b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd, 28386b96018bSArnd Bergmann struct compat_ifreq __user *ifr32) 28397a229387SArnd Bergmann { 28407a229387SArnd Bergmann struct ifreq kifr; 28417a229387SArnd Bergmann struct ifreq __user *uifr; 28427a229387SArnd Bergmann mm_segment_t old_fs; 28437a229387SArnd Bergmann int err; 28447a229387SArnd Bergmann u32 data; 28457a229387SArnd Bergmann void __user *datap; 28467a229387SArnd Bergmann 28477a229387SArnd Bergmann switch (cmd) { 28487a229387SArnd Bergmann case SIOCBONDENSLAVE: 28497a229387SArnd Bergmann case SIOCBONDRELEASE: 28507a229387SArnd Bergmann case SIOCBONDSETHWADDR: 28517a229387SArnd Bergmann case SIOCBONDCHANGEACTIVE: 28526b96018bSArnd Bergmann if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq))) 28537a229387SArnd Bergmann return -EFAULT; 28547a229387SArnd Bergmann 28557a229387SArnd Bergmann old_fs = get_fs(); 28567a229387SArnd Bergmann set_fs(KERNEL_DS); 2857c3f52ae6Sstephen hemminger err = dev_ioctl(net, cmd, 2858c3f52ae6Sstephen hemminger (struct ifreq __user __force *) &kifr); 28597a229387SArnd Bergmann set_fs(old_fs); 28607a229387SArnd Bergmann 28617a229387SArnd Bergmann return err; 28627a229387SArnd Bergmann case SIOCBONDSLAVEINFOQUERY: 28637a229387SArnd Bergmann case SIOCBONDINFOQUERY: 28647a229387SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 28657a229387SArnd Bergmann if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 28667a229387SArnd Bergmann return -EFAULT; 28677a229387SArnd Bergmann 28687a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 28697a229387SArnd Bergmann return -EFAULT; 28707a229387SArnd Bergmann 28717a229387SArnd Bergmann datap = compat_ptr(data); 28727a229387SArnd Bergmann if (put_user(datap, &uifr->ifr_ifru.ifru_data)) 28737a229387SArnd Bergmann return -EFAULT; 28747a229387SArnd Bergmann 28756b96018bSArnd Bergmann return dev_ioctl(net, cmd, uifr); 28767a229387SArnd Bergmann default: 28777a229387SArnd Bergmann return -EINVAL; 2878ccbd6a5aSJoe Perches } 28797a229387SArnd Bergmann } 28807a229387SArnd Bergmann 28816b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, 28826b96018bSArnd Bergmann struct compat_ifreq __user *u_ifreq32) 28837a229387SArnd Bergmann { 28847a229387SArnd Bergmann struct ifreq __user *u_ifreq64; 28857a229387SArnd Bergmann char tmp_buf[IFNAMSIZ]; 28867a229387SArnd Bergmann void __user *data64; 28877a229387SArnd Bergmann u32 data32; 28887a229387SArnd Bergmann 28897a229387SArnd Bergmann if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), 28907a229387SArnd Bergmann IFNAMSIZ)) 28917a229387SArnd Bergmann return -EFAULT; 28927a229387SArnd Bergmann if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) 28937a229387SArnd Bergmann return -EFAULT; 28947a229387SArnd Bergmann data64 = compat_ptr(data32); 28957a229387SArnd Bergmann 28967a229387SArnd Bergmann u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); 28977a229387SArnd Bergmann 28987a229387SArnd Bergmann /* Don't check these user accesses, just let that get trapped 28997a229387SArnd Bergmann * in the ioctl handler instead. 29007a229387SArnd Bergmann */ 29017a229387SArnd Bergmann if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], 29027a229387SArnd Bergmann IFNAMSIZ)) 29037a229387SArnd Bergmann return -EFAULT; 29047a229387SArnd Bergmann if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) 29057a229387SArnd Bergmann return -EFAULT; 29067a229387SArnd Bergmann 29076b96018bSArnd Bergmann return dev_ioctl(net, cmd, u_ifreq64); 29087a229387SArnd Bergmann } 29097a229387SArnd Bergmann 29106b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock, 29116b96018bSArnd Bergmann unsigned int cmd, struct compat_ifreq __user *uifr32) 29127a229387SArnd Bergmann { 2913a2116ed2SArnd Bergmann struct ifreq __user *uifr; 29147a229387SArnd Bergmann int err; 29157a229387SArnd Bergmann 2916a2116ed2SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 2917a2116ed2SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(*uifr32))) 29187a229387SArnd Bergmann return -EFAULT; 2919a2116ed2SArnd Bergmann 2920a2116ed2SArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr); 2921a2116ed2SArnd Bergmann 29227a229387SArnd Bergmann if (!err) { 29237a229387SArnd Bergmann switch (cmd) { 29247a229387SArnd Bergmann case SIOCGIFFLAGS: 29257a229387SArnd Bergmann case SIOCGIFMETRIC: 29267a229387SArnd Bergmann case SIOCGIFMTU: 29277a229387SArnd Bergmann case SIOCGIFMEM: 29287a229387SArnd Bergmann case SIOCGIFHWADDR: 29297a229387SArnd Bergmann case SIOCGIFINDEX: 29307a229387SArnd Bergmann case SIOCGIFADDR: 29317a229387SArnd Bergmann case SIOCGIFBRDADDR: 29327a229387SArnd Bergmann case SIOCGIFDSTADDR: 29337a229387SArnd Bergmann case SIOCGIFNETMASK: 2934fab2532bSArnd Bergmann case SIOCGIFPFLAGS: 29357a229387SArnd Bergmann case SIOCGIFTXQLEN: 2936fab2532bSArnd Bergmann case SIOCGMIIPHY: 2937fab2532bSArnd Bergmann case SIOCGMIIREG: 2938a2116ed2SArnd Bergmann if (copy_in_user(uifr32, uifr, sizeof(*uifr32))) 2939a2116ed2SArnd Bergmann err = -EFAULT; 29407a229387SArnd Bergmann break; 2941a2116ed2SArnd Bergmann } 2942a2116ed2SArnd Bergmann } 2943a2116ed2SArnd Bergmann return err; 2944a2116ed2SArnd Bergmann } 2945a2116ed2SArnd Bergmann 2946a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 2947a2116ed2SArnd Bergmann struct compat_ifreq __user *uifr32) 2948a2116ed2SArnd Bergmann { 2949a2116ed2SArnd Bergmann struct ifreq ifr; 2950a2116ed2SArnd Bergmann struct compat_ifmap __user *uifmap32; 2951a2116ed2SArnd Bergmann mm_segment_t old_fs; 2952a2116ed2SArnd Bergmann int err; 2953a2116ed2SArnd Bergmann 2954a2116ed2SArnd Bergmann uifmap32 = &uifr32->ifr_ifru.ifru_map; 2955a2116ed2SArnd Bergmann err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); 2956a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 2957a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 2958a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 2959a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq); 2960a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma); 2961a2116ed2SArnd Bergmann err |= __get_user(ifr.ifr_map.port, &uifmap32->port); 2962a2116ed2SArnd Bergmann if (err) 2963a2116ed2SArnd Bergmann return -EFAULT; 2964a2116ed2SArnd Bergmann 2965a2116ed2SArnd Bergmann old_fs = get_fs(); 2966a2116ed2SArnd Bergmann set_fs(KERNEL_DS); 2967c3f52ae6Sstephen hemminger err = dev_ioctl(net, cmd, (void __user __force *)&ifr); 2968a2116ed2SArnd Bergmann set_fs(old_fs); 2969a2116ed2SArnd Bergmann 2970a2116ed2SArnd Bergmann if (cmd == SIOCGIFMAP && !err) { 29717a229387SArnd Bergmann err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); 29727a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 29737a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 29747a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 29757a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq); 29767a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma); 29777a229387SArnd Bergmann err |= __put_user(ifr.ifr_map.port, &uifmap32->port); 29787a229387SArnd Bergmann if (err) 29797a229387SArnd Bergmann err = -EFAULT; 29807a229387SArnd Bergmann } 29817a229387SArnd Bergmann return err; 29827a229387SArnd Bergmann } 29837a229387SArnd Bergmann 2984a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32) 2985a2116ed2SArnd Bergmann { 2986a2116ed2SArnd Bergmann void __user *uptr; 2987a2116ed2SArnd Bergmann compat_uptr_t uptr32; 2988a2116ed2SArnd Bergmann struct ifreq __user *uifr; 2989a2116ed2SArnd Bergmann 2990a2116ed2SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 2991a2116ed2SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 2992a2116ed2SArnd Bergmann return -EFAULT; 2993a2116ed2SArnd Bergmann 2994a2116ed2SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_data)) 2995a2116ed2SArnd Bergmann return -EFAULT; 2996a2116ed2SArnd Bergmann 2997a2116ed2SArnd Bergmann uptr = compat_ptr(uptr32); 2998a2116ed2SArnd Bergmann 2999a2116ed2SArnd Bergmann if (put_user(uptr, &uifr->ifr_data)) 3000a2116ed2SArnd Bergmann return -EFAULT; 3001a2116ed2SArnd Bergmann 3002a2116ed2SArnd Bergmann return dev_ioctl(net, SIOCSHWTSTAMP, uifr); 3003a2116ed2SArnd Bergmann } 3004a2116ed2SArnd Bergmann 30057a229387SArnd Bergmann struct rtentry32 { 30067a229387SArnd Bergmann u32 rt_pad1; 30077a229387SArnd Bergmann struct sockaddr rt_dst; /* target address */ 30087a229387SArnd Bergmann struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ 30097a229387SArnd Bergmann struct sockaddr rt_genmask; /* target network mask (IP) */ 30107a229387SArnd Bergmann unsigned short rt_flags; 30117a229387SArnd Bergmann short rt_pad2; 30127a229387SArnd Bergmann u32 rt_pad3; 30137a229387SArnd Bergmann unsigned char rt_tos; 30147a229387SArnd Bergmann unsigned char rt_class; 30157a229387SArnd Bergmann short rt_pad4; 30167a229387SArnd Bergmann short rt_metric; /* +1 for binary compatibility! */ 30177a229387SArnd Bergmann /* char * */ u32 rt_dev; /* forcing the device at add */ 30187a229387SArnd Bergmann u32 rt_mtu; /* per route MTU/Window */ 30197a229387SArnd Bergmann u32 rt_window; /* Window clamping */ 30207a229387SArnd Bergmann unsigned short rt_irtt; /* Initial RTT */ 30217a229387SArnd Bergmann }; 30227a229387SArnd Bergmann 30237a229387SArnd Bergmann struct in6_rtmsg32 { 30247a229387SArnd Bergmann struct in6_addr rtmsg_dst; 30257a229387SArnd Bergmann struct in6_addr rtmsg_src; 30267a229387SArnd Bergmann struct in6_addr rtmsg_gateway; 30277a229387SArnd Bergmann u32 rtmsg_type; 30287a229387SArnd Bergmann u16 rtmsg_dst_len; 30297a229387SArnd Bergmann u16 rtmsg_src_len; 30307a229387SArnd Bergmann u32 rtmsg_metric; 30317a229387SArnd Bergmann u32 rtmsg_info; 30327a229387SArnd Bergmann u32 rtmsg_flags; 30337a229387SArnd Bergmann s32 rtmsg_ifindex; 30347a229387SArnd Bergmann }; 30357a229387SArnd Bergmann 30366b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock, 30376b96018bSArnd Bergmann unsigned int cmd, void __user *argp) 30387a229387SArnd Bergmann { 30397a229387SArnd Bergmann int ret; 30407a229387SArnd Bergmann void *r = NULL; 30417a229387SArnd Bergmann struct in6_rtmsg r6; 30427a229387SArnd Bergmann struct rtentry r4; 30437a229387SArnd Bergmann char devname[16]; 30447a229387SArnd Bergmann u32 rtdev; 30457a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 30467a229387SArnd Bergmann 30476b96018bSArnd Bergmann if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */ 30486b96018bSArnd Bergmann struct in6_rtmsg32 __user *ur6 = argp; 30497a229387SArnd Bergmann ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst), 30507a229387SArnd Bergmann 3 * sizeof(struct in6_addr)); 30517a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type)); 30527a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); 30537a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); 30547a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric)); 30557a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info)); 30567a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags)); 30577a229387SArnd Bergmann ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); 30587a229387SArnd Bergmann 30597a229387SArnd Bergmann r = (void *) &r6; 30607a229387SArnd Bergmann } else { /* ipv4 */ 30616b96018bSArnd Bergmann struct rtentry32 __user *ur4 = argp; 30627a229387SArnd Bergmann ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst), 30637a229387SArnd Bergmann 3 * sizeof(struct sockaddr)); 30647a229387SArnd Bergmann ret |= __get_user(r4.rt_flags, &(ur4->rt_flags)); 30657a229387SArnd Bergmann ret |= __get_user(r4.rt_metric, &(ur4->rt_metric)); 30667a229387SArnd Bergmann ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu)); 30677a229387SArnd Bergmann ret |= __get_user(r4.rt_window, &(ur4->rt_window)); 30687a229387SArnd Bergmann ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt)); 30697a229387SArnd Bergmann ret |= __get_user(rtdev, &(ur4->rt_dev)); 30707a229387SArnd Bergmann if (rtdev) { 30717a229387SArnd Bergmann ret |= copy_from_user(devname, compat_ptr(rtdev), 15); 3072c3f52ae6Sstephen hemminger r4.rt_dev = (char __user __force *)devname; 3073c3f52ae6Sstephen hemminger devname[15] = 0; 30747a229387SArnd Bergmann } else 30757a229387SArnd Bergmann r4.rt_dev = NULL; 30767a229387SArnd Bergmann 30777a229387SArnd Bergmann r = (void *) &r4; 30787a229387SArnd Bergmann } 30797a229387SArnd Bergmann 30807a229387SArnd Bergmann if (ret) { 30817a229387SArnd Bergmann ret = -EFAULT; 30827a229387SArnd Bergmann goto out; 30837a229387SArnd Bergmann } 30847a229387SArnd Bergmann 30857a229387SArnd Bergmann set_fs(KERNEL_DS); 30866b96018bSArnd Bergmann ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); 30877a229387SArnd Bergmann set_fs(old_fs); 30887a229387SArnd Bergmann 30897a229387SArnd Bergmann out: 30907a229387SArnd Bergmann return ret; 30917a229387SArnd Bergmann } 30927a229387SArnd Bergmann 30937a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE 30947a229387SArnd Bergmann * for some operations; this forces use of the newer bridge-utils that 309525985edcSLucas De Marchi * use compatible ioctls 30967a229387SArnd Bergmann */ 30976b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp) 30987a229387SArnd Bergmann { 30996b96018bSArnd Bergmann compat_ulong_t tmp; 31007a229387SArnd Bergmann 31016b96018bSArnd Bergmann if (get_user(tmp, argp)) 31027a229387SArnd Bergmann return -EFAULT; 31037a229387SArnd Bergmann if (tmp == BRCTL_GET_VERSION) 31047a229387SArnd Bergmann return BRCTL_VERSION + 1; 31057a229387SArnd Bergmann return -EINVAL; 31067a229387SArnd Bergmann } 31077a229387SArnd Bergmann 31086b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, 31096b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 31106b96018bSArnd Bergmann { 31116b96018bSArnd Bergmann void __user *argp = compat_ptr(arg); 31126b96018bSArnd Bergmann struct sock *sk = sock->sk; 31136b96018bSArnd Bergmann struct net *net = sock_net(sk); 31147a229387SArnd Bergmann 31156b96018bSArnd Bergmann if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 31166b96018bSArnd Bergmann return siocdevprivate_ioctl(net, cmd, argp); 31177a229387SArnd Bergmann 31186b96018bSArnd Bergmann switch (cmd) { 31196b96018bSArnd Bergmann case SIOCSIFBR: 31206b96018bSArnd Bergmann case SIOCGIFBR: 31216b96018bSArnd Bergmann return old_bridge_ioctl(argp); 31226b96018bSArnd Bergmann case SIOCGIFNAME: 31236b96018bSArnd Bergmann return dev_ifname32(net, argp); 31246b96018bSArnd Bergmann case SIOCGIFCONF: 31256b96018bSArnd Bergmann return dev_ifconf(net, argp); 31266b96018bSArnd Bergmann case SIOCETHTOOL: 31276b96018bSArnd Bergmann return ethtool_ioctl(net, argp); 31287a50a240SArnd Bergmann case SIOCWANDEV: 31297a50a240SArnd Bergmann return compat_siocwandev(net, argp); 3130a2116ed2SArnd Bergmann case SIOCGIFMAP: 3131a2116ed2SArnd Bergmann case SIOCSIFMAP: 3132a2116ed2SArnd Bergmann return compat_sioc_ifmap(net, cmd, argp); 31336b96018bSArnd Bergmann case SIOCBONDENSLAVE: 31346b96018bSArnd Bergmann case SIOCBONDRELEASE: 31356b96018bSArnd Bergmann case SIOCBONDSETHWADDR: 31366b96018bSArnd Bergmann case SIOCBONDSLAVEINFOQUERY: 31376b96018bSArnd Bergmann case SIOCBONDINFOQUERY: 31386b96018bSArnd Bergmann case SIOCBONDCHANGEACTIVE: 31396b96018bSArnd Bergmann return bond_ioctl(net, cmd, argp); 31406b96018bSArnd Bergmann case SIOCADDRT: 31416b96018bSArnd Bergmann case SIOCDELRT: 31426b96018bSArnd Bergmann return routing_ioctl(net, sock, cmd, argp); 31436b96018bSArnd Bergmann case SIOCGSTAMP: 31446b96018bSArnd Bergmann return do_siocgstamp(net, sock, cmd, argp); 31456b96018bSArnd Bergmann case SIOCGSTAMPNS: 31466b96018bSArnd Bergmann return do_siocgstampns(net, sock, cmd, argp); 3147a2116ed2SArnd Bergmann case SIOCSHWTSTAMP: 3148a2116ed2SArnd Bergmann return compat_siocshwtstamp(net, argp); 31497a229387SArnd Bergmann 31506b96018bSArnd Bergmann case FIOSETOWN: 31516b96018bSArnd Bergmann case SIOCSPGRP: 31526b96018bSArnd Bergmann case FIOGETOWN: 31536b96018bSArnd Bergmann case SIOCGPGRP: 31546b96018bSArnd Bergmann case SIOCBRADDBR: 31556b96018bSArnd Bergmann case SIOCBRDELBR: 31566b96018bSArnd Bergmann case SIOCGIFVLAN: 31576b96018bSArnd Bergmann case SIOCSIFVLAN: 31586b96018bSArnd Bergmann case SIOCADDDLCI: 31596b96018bSArnd Bergmann case SIOCDELDLCI: 31606b96018bSArnd Bergmann return sock_ioctl(file, cmd, arg); 31616b96018bSArnd Bergmann 31626b96018bSArnd Bergmann case SIOCGIFFLAGS: 31636b96018bSArnd Bergmann case SIOCSIFFLAGS: 31646b96018bSArnd Bergmann case SIOCGIFMETRIC: 31656b96018bSArnd Bergmann case SIOCSIFMETRIC: 31666b96018bSArnd Bergmann case SIOCGIFMTU: 31676b96018bSArnd Bergmann case SIOCSIFMTU: 31686b96018bSArnd Bergmann case SIOCGIFMEM: 31696b96018bSArnd Bergmann case SIOCSIFMEM: 31706b96018bSArnd Bergmann case SIOCGIFHWADDR: 31716b96018bSArnd Bergmann case SIOCSIFHWADDR: 31726b96018bSArnd Bergmann case SIOCADDMULTI: 31736b96018bSArnd Bergmann case SIOCDELMULTI: 31746b96018bSArnd Bergmann case SIOCGIFINDEX: 31756b96018bSArnd Bergmann case SIOCGIFADDR: 31766b96018bSArnd Bergmann case SIOCSIFADDR: 31776b96018bSArnd Bergmann case SIOCSIFHWBROADCAST: 31786b96018bSArnd Bergmann case SIOCDIFADDR: 31796b96018bSArnd Bergmann case SIOCGIFBRDADDR: 31806b96018bSArnd Bergmann case SIOCSIFBRDADDR: 31816b96018bSArnd Bergmann case SIOCGIFDSTADDR: 31826b96018bSArnd Bergmann case SIOCSIFDSTADDR: 31836b96018bSArnd Bergmann case SIOCGIFNETMASK: 31846b96018bSArnd Bergmann case SIOCSIFNETMASK: 31856b96018bSArnd Bergmann case SIOCSIFPFLAGS: 31866b96018bSArnd Bergmann case SIOCGIFPFLAGS: 31876b96018bSArnd Bergmann case SIOCGIFTXQLEN: 31886b96018bSArnd Bergmann case SIOCSIFTXQLEN: 31896b96018bSArnd Bergmann case SIOCBRADDIF: 31906b96018bSArnd Bergmann case SIOCBRDELIF: 31919177efd3SArnd Bergmann case SIOCSIFNAME: 31929177efd3SArnd Bergmann case SIOCGMIIPHY: 31939177efd3SArnd Bergmann case SIOCGMIIREG: 31949177efd3SArnd Bergmann case SIOCSMIIREG: 31956b96018bSArnd Bergmann return dev_ifsioc(net, sock, cmd, argp); 31969177efd3SArnd Bergmann 31976b96018bSArnd Bergmann case SIOCSARP: 31986b96018bSArnd Bergmann case SIOCGARP: 31996b96018bSArnd Bergmann case SIOCDARP: 32006b96018bSArnd Bergmann case SIOCATMARK: 32019177efd3SArnd Bergmann return sock_do_ioctl(net, sock, cmd, arg); 32029177efd3SArnd Bergmann } 32039177efd3SArnd Bergmann 32049177efd3SArnd Bergmann /* Prevent warning from compat_sys_ioctl, these always 32059177efd3SArnd Bergmann * result in -EINVAL in the native case anyway. */ 32069177efd3SArnd Bergmann switch (cmd) { 32079177efd3SArnd Bergmann case SIOCRTMSG: 32089177efd3SArnd Bergmann case SIOCGIFCOUNT: 32096b96018bSArnd Bergmann case SIOCSRARP: 32106b96018bSArnd Bergmann case SIOCGRARP: 32116b96018bSArnd Bergmann case SIOCDRARP: 32129177efd3SArnd Bergmann case SIOCSIFLINK: 32139177efd3SArnd Bergmann case SIOCGIFSLAVE: 32149177efd3SArnd Bergmann case SIOCSIFSLAVE: 32159177efd3SArnd Bergmann return -EINVAL; 32166b96018bSArnd Bergmann } 32176b96018bSArnd Bergmann 32186b96018bSArnd Bergmann return -ENOIOCTLCMD; 32196b96018bSArnd Bergmann } 32207a229387SArnd Bergmann 322189bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, unsigned cmd, 322289bbfc95SShaun Pereira unsigned long arg) 322389bbfc95SShaun Pereira { 322489bbfc95SShaun Pereira struct socket *sock = file->private_data; 322589bbfc95SShaun Pereira int ret = -ENOIOCTLCMD; 322687de87d5SDavid S. Miller struct sock *sk; 322787de87d5SDavid S. Miller struct net *net; 322887de87d5SDavid S. Miller 322987de87d5SDavid S. Miller sk = sock->sk; 323087de87d5SDavid S. Miller net = sock_net(sk); 323189bbfc95SShaun Pereira 323289bbfc95SShaun Pereira if (sock->ops->compat_ioctl) 323389bbfc95SShaun Pereira ret = sock->ops->compat_ioctl(sock, cmd, arg); 323489bbfc95SShaun Pereira 323587de87d5SDavid S. Miller if (ret == -ENOIOCTLCMD && 323687de87d5SDavid S. Miller (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) 323787de87d5SDavid S. Miller ret = compat_wext_handle_ioctl(net, cmd, arg); 323887de87d5SDavid S. Miller 32396b96018bSArnd Bergmann if (ret == -ENOIOCTLCMD) 32406b96018bSArnd Bergmann ret = compat_sock_ioctl_trans(file, sock, cmd, arg); 32416b96018bSArnd Bergmann 324289bbfc95SShaun Pereira return ret; 324389bbfc95SShaun Pereira } 324489bbfc95SShaun Pereira #endif 324589bbfc95SShaun Pereira 3246ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) 3247ac5a488eSSridhar Samudrala { 3248ac5a488eSSridhar Samudrala return sock->ops->bind(sock, addr, addrlen); 3249ac5a488eSSridhar Samudrala } 3250c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind); 3251ac5a488eSSridhar Samudrala 3252ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog) 3253ac5a488eSSridhar Samudrala { 3254ac5a488eSSridhar Samudrala return sock->ops->listen(sock, backlog); 3255ac5a488eSSridhar Samudrala } 3256c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen); 3257ac5a488eSSridhar Samudrala 3258ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags) 3259ac5a488eSSridhar Samudrala { 3260ac5a488eSSridhar Samudrala struct sock *sk = sock->sk; 3261ac5a488eSSridhar Samudrala int err; 3262ac5a488eSSridhar Samudrala 3263ac5a488eSSridhar Samudrala err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, 3264ac5a488eSSridhar Samudrala newsock); 3265ac5a488eSSridhar Samudrala if (err < 0) 3266ac5a488eSSridhar Samudrala goto done; 3267ac5a488eSSridhar Samudrala 3268ac5a488eSSridhar Samudrala err = sock->ops->accept(sock, *newsock, flags); 3269ac5a488eSSridhar Samudrala if (err < 0) { 3270ac5a488eSSridhar Samudrala sock_release(*newsock); 3271fa8705b0STony Battersby *newsock = NULL; 3272ac5a488eSSridhar Samudrala goto done; 3273ac5a488eSSridhar Samudrala } 3274ac5a488eSSridhar Samudrala 3275ac5a488eSSridhar Samudrala (*newsock)->ops = sock->ops; 32761b08534eSWei Yongjun __module_get((*newsock)->ops->owner); 3277ac5a488eSSridhar Samudrala 3278ac5a488eSSridhar Samudrala done: 3279ac5a488eSSridhar Samudrala return err; 3280ac5a488eSSridhar Samudrala } 3281c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept); 3282ac5a488eSSridhar Samudrala 3283ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, 3284ac5a488eSSridhar Samudrala int flags) 3285ac5a488eSSridhar Samudrala { 3286ac5a488eSSridhar Samudrala return sock->ops->connect(sock, addr, addrlen, flags); 3287ac5a488eSSridhar Samudrala } 3288c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect); 3289ac5a488eSSridhar Samudrala 3290ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr, 3291ac5a488eSSridhar Samudrala int *addrlen) 3292ac5a488eSSridhar Samudrala { 3293ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 0); 3294ac5a488eSSridhar Samudrala } 3295c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname); 3296ac5a488eSSridhar Samudrala 3297ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr, 3298ac5a488eSSridhar Samudrala int *addrlen) 3299ac5a488eSSridhar Samudrala { 3300ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 1); 3301ac5a488eSSridhar Samudrala } 3302c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername); 3303ac5a488eSSridhar Samudrala 3304ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname, 3305ac5a488eSSridhar Samudrala char *optval, int *optlen) 3306ac5a488eSSridhar Samudrala { 3307ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3308fb8621bbSNamhyung Kim char __user *uoptval; 3309fb8621bbSNamhyung Kim int __user *uoptlen; 3310ac5a488eSSridhar Samudrala int err; 3311ac5a488eSSridhar Samudrala 3312fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3313fb8621bbSNamhyung Kim uoptlen = (int __user __force *) optlen; 3314fb8621bbSNamhyung Kim 3315ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3316ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3317fb8621bbSNamhyung Kim err = sock_getsockopt(sock, level, optname, uoptval, uoptlen); 3318ac5a488eSSridhar Samudrala else 3319fb8621bbSNamhyung Kim err = sock->ops->getsockopt(sock, level, optname, uoptval, 3320fb8621bbSNamhyung Kim uoptlen); 3321ac5a488eSSridhar Samudrala set_fs(oldfs); 3322ac5a488eSSridhar Samudrala return err; 3323ac5a488eSSridhar Samudrala } 3324c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt); 3325ac5a488eSSridhar Samudrala 3326ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname, 3327b7058842SDavid S. Miller char *optval, unsigned int optlen) 3328ac5a488eSSridhar Samudrala { 3329ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3330fb8621bbSNamhyung Kim char __user *uoptval; 3331ac5a488eSSridhar Samudrala int err; 3332ac5a488eSSridhar Samudrala 3333fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3334fb8621bbSNamhyung Kim 3335ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3336ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3337fb8621bbSNamhyung Kim err = sock_setsockopt(sock, level, optname, uoptval, optlen); 3338ac5a488eSSridhar Samudrala else 3339fb8621bbSNamhyung Kim err = sock->ops->setsockopt(sock, level, optname, uoptval, 3340ac5a488eSSridhar Samudrala optlen); 3341ac5a488eSSridhar Samudrala set_fs(oldfs); 3342ac5a488eSSridhar Samudrala return err; 3343ac5a488eSSridhar Samudrala } 3344c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt); 3345ac5a488eSSridhar Samudrala 3346ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset, 3347ac5a488eSSridhar Samudrala size_t size, int flags) 3348ac5a488eSSridhar Samudrala { 3349f8451725SHerbert Xu sock_update_classid(sock->sk); 3350f8451725SHerbert Xu 3351ac5a488eSSridhar Samudrala if (sock->ops->sendpage) 3352ac5a488eSSridhar Samudrala return sock->ops->sendpage(sock, page, offset, size, flags); 3353ac5a488eSSridhar Samudrala 3354ac5a488eSSridhar Samudrala return sock_no_sendpage(sock, page, offset, size, flags); 3355ac5a488eSSridhar Samudrala } 3356c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage); 3357ac5a488eSSridhar Samudrala 3358ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg) 3359ac5a488eSSridhar Samudrala { 3360ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3361ac5a488eSSridhar Samudrala int err; 3362ac5a488eSSridhar Samudrala 3363ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3364ac5a488eSSridhar Samudrala err = sock->ops->ioctl(sock, cmd, arg); 3365ac5a488eSSridhar Samudrala set_fs(oldfs); 3366ac5a488eSSridhar Samudrala 3367ac5a488eSSridhar Samudrala return err; 3368ac5a488eSSridhar Samudrala } 3369c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl); 3370ac5a488eSSridhar Samudrala 337191cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) 337291cf45f0STrond Myklebust { 337391cf45f0STrond Myklebust return sock->ops->shutdown(sock, how); 337491cf45f0STrond Myklebust } 337591cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown); 3376