11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * NET An implementation of the SOCKET network access protocol. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Version: @(#)socket.c 1.1.93 18/02/95 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Authors: Orest Zborowski, <obz@Kodak.COM> 702c30a84SJesper Juhl * Ross Biro 81da177e4SLinus Torvalds * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * Fixes: 111da177e4SLinus Torvalds * Anonymous : NOTSOCK/BADF cleanup. Error fix in 121da177e4SLinus Torvalds * shutdown() 131da177e4SLinus Torvalds * Alan Cox : verify_area() fixes 141da177e4SLinus Torvalds * Alan Cox : Removed DDI 151da177e4SLinus Torvalds * Jonathan Kamens : SOCK_DGRAM reconnect bug 161da177e4SLinus Torvalds * Alan Cox : Moved a load of checks to the very 171da177e4SLinus Torvalds * top level. 181da177e4SLinus Torvalds * Alan Cox : Move address structures to/from user 191da177e4SLinus Torvalds * mode above the protocol layers. 201da177e4SLinus Torvalds * Rob Janssen : Allow 0 length sends. 211da177e4SLinus Torvalds * Alan Cox : Asynchronous I/O support (cribbed from the 221da177e4SLinus Torvalds * tty drivers). 231da177e4SLinus Torvalds * Niibe Yutaka : Asynchronous I/O for writes (4.4BSD style) 241da177e4SLinus Torvalds * Jeff Uphoff : Made max number of sockets command-line 251da177e4SLinus Torvalds * configurable. 261da177e4SLinus Torvalds * Matti Aarnio : Made the number of sockets dynamic, 271da177e4SLinus Torvalds * to be allocated when needed, and mr. 281da177e4SLinus Torvalds * Uphoff's max is used as max to be 291da177e4SLinus Torvalds * allowed to allocate. 301da177e4SLinus Torvalds * Linus : Argh. removed all the socket allocation 311da177e4SLinus Torvalds * altogether: it's in the inode now. 321da177e4SLinus Torvalds * Alan Cox : Made sock_alloc()/sock_release() public 331da177e4SLinus Torvalds * for NetROM and future kernel nfsd type 341da177e4SLinus Torvalds * stuff. 351da177e4SLinus Torvalds * Alan Cox : sendmsg/recvmsg basics. 361da177e4SLinus Torvalds * Tom Dyas : Export net symbols. 371da177e4SLinus Torvalds * Marcin Dalecki : Fixed problems with CONFIG_NET="n". 381da177e4SLinus Torvalds * Alan Cox : Added thread locking to sys_* calls 391da177e4SLinus Torvalds * for sockets. May have errors at the 401da177e4SLinus Torvalds * moment. 411da177e4SLinus Torvalds * Kevin Buhr : Fixed the dumb errors in the above. 421da177e4SLinus Torvalds * Andi Kleen : Some small cleanups, optimizations, 431da177e4SLinus Torvalds * and fixed a copy_from_user() bug. 441da177e4SLinus Torvalds * Tigran Aivazian : sys_send(args) calls sys_sendto(args, NULL, 0) 451da177e4SLinus Torvalds * Tigran Aivazian : Made listen(2) backlog sanity checks 461da177e4SLinus Torvalds * protocol-independent 471da177e4SLinus Torvalds * 481da177e4SLinus Torvalds * 491da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 501da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 511da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 521da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 531da177e4SLinus Torvalds * 541da177e4SLinus Torvalds * 551da177e4SLinus Torvalds * This module is effectively the top level interface to the BSD socket 561da177e4SLinus Torvalds * paradigm. 571da177e4SLinus Torvalds * 581da177e4SLinus Torvalds * Based upon Swansea University Computer Society NET3.039 591da177e4SLinus Torvalds */ 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds #include <linux/mm.h> 621da177e4SLinus Torvalds #include <linux/socket.h> 631da177e4SLinus Torvalds #include <linux/file.h> 641da177e4SLinus Torvalds #include <linux/net.h> 651da177e4SLinus Torvalds #include <linux/interrupt.h> 66aaca0bdcSUlrich Drepper #include <linux/thread_info.h> 6755737fdaSStephen Hemminger #include <linux/rcupdate.h> 681da177e4SLinus Torvalds #include <linux/netdevice.h> 691da177e4SLinus Torvalds #include <linux/proc_fs.h> 701da177e4SLinus Torvalds #include <linux/seq_file.h> 714a3e2f71SArjan van de Ven #include <linux/mutex.h> 721da177e4SLinus Torvalds #include <linux/if_bridge.h> 7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h> 7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h> 75408eccceSDaniel Borkmann #include <linux/ptp_classify.h> 761da177e4SLinus Torvalds #include <linux/init.h> 771da177e4SLinus Torvalds #include <linux/poll.h> 781da177e4SLinus Torvalds #include <linux/cache.h> 791da177e4SLinus Torvalds #include <linux/module.h> 801da177e4SLinus Torvalds #include <linux/highmem.h> 811da177e4SLinus Torvalds #include <linux/mount.h> 821da177e4SLinus Torvalds #include <linux/security.h> 831da177e4SLinus Torvalds #include <linux/syscalls.h> 841da177e4SLinus Torvalds #include <linux/compat.h> 851da177e4SLinus Torvalds #include <linux/kmod.h> 863ec3b2fbSDavid Woodhouse #include <linux/audit.h> 87d86b5e0eSAdrian Bunk #include <linux/wireless.h> 881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h> 891fd7317dSNick Black #include <linux/magic.h> 905a0e3ad6STejun Heo #include <linux/slab.h> 91600e1779SMasatake YAMATO #include <linux/xattr.h> 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds #include <asm/uaccess.h> 941da177e4SLinus Torvalds #include <asm/unistd.h> 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds #include <net/compat.h> 9787de87d5SDavid S. Miller #include <net/wext.h> 98f8451725SHerbert Xu #include <net/cls_cgroup.h> 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds #include <net/sock.h> 1011da177e4SLinus Torvalds #include <linux/netfilter.h> 1021da177e4SLinus Torvalds 1036b96018bSArnd Bergmann #include <linux/if_tun.h> 1046b96018bSArnd Bergmann #include <linux/ipv6_route.h> 1056b96018bSArnd Bergmann #include <linux/route.h> 1066b96018bSArnd Bergmann #include <linux/sockios.h> 1076b96018bSArnd Bergmann #include <linux/atalk.h> 108076bb0c8SEliezer Tamir #include <net/busy_poll.h> 109f24b9be5SWillem de Bruijn #include <linux/errqueue.h> 11006021292SEliezer Tamir 111e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL 11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly; 11364b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly; 11406021292SEliezer Tamir #endif 1156b96018bSArnd Bergmann 116*8ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to); 117*8ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from); 1181da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma); 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file); 1211da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, 1221da177e4SLinus Torvalds struct poll_table_struct *wait); 12389bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 12489bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 12589bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, 12689bbfc95SShaun Pereira unsigned int cmd, unsigned long arg); 12789bbfc95SShaun Pereira #endif 1281da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on); 1291da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page, 1301da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more); 1319c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 1329c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 1339c55e01cSJens Axboe unsigned int flags); 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds /* 1361da177e4SLinus Torvalds * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear 1371da177e4SLinus Torvalds * in the operation structures but are done directly via the socketcall() multiplexor. 1381da177e4SLinus Torvalds */ 1391da177e4SLinus Torvalds 140da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = { 1411da177e4SLinus Torvalds .owner = THIS_MODULE, 1421da177e4SLinus Torvalds .llseek = no_llseek, 143*8ae5e030SAl Viro .read = new_sync_read, 144*8ae5e030SAl Viro .write = new_sync_write, 145*8ae5e030SAl Viro .read_iter = sock_read_iter, 146*8ae5e030SAl Viro .write_iter = sock_write_iter, 1471da177e4SLinus Torvalds .poll = sock_poll, 1481da177e4SLinus Torvalds .unlocked_ioctl = sock_ioctl, 14989bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 15089bbfc95SShaun Pereira .compat_ioctl = compat_sock_ioctl, 15189bbfc95SShaun Pereira #endif 1521da177e4SLinus Torvalds .mmap = sock_mmap, 1531da177e4SLinus Torvalds .release = sock_close, 1541da177e4SLinus Torvalds .fasync = sock_fasync, 1555274f052SJens Axboe .sendpage = sock_sendpage, 1565274f052SJens Axboe .splice_write = generic_splice_sendpage, 1579c55e01cSJens Axboe .splice_read = sock_splice_read, 1581da177e4SLinus Torvalds }; 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds /* 1611da177e4SLinus Torvalds * The protocol list. Each protocol is registered in here. 1621da177e4SLinus Torvalds */ 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock); 165190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds /* 1681da177e4SLinus Torvalds * Statistics counters of the socket lists 1691da177e4SLinus Torvalds */ 1701da177e4SLinus Torvalds 171c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use); 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds /* 17489bddce5SStephen Hemminger * Support routines. 17589bddce5SStephen Hemminger * Move socket addresses back and forth across the kernel/user 1761da177e4SLinus Torvalds * divide and look after the messy bits. 1771da177e4SLinus Torvalds */ 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds /** 1801da177e4SLinus Torvalds * move_addr_to_kernel - copy a socket address into kernel space 1811da177e4SLinus Torvalds * @uaddr: Address in user space 1821da177e4SLinus Torvalds * @kaddr: Address in kernel space 1831da177e4SLinus Torvalds * @ulen: Length in user space 1841da177e4SLinus Torvalds * 1851da177e4SLinus Torvalds * The address is copied into kernel space. If the provided address is 1861da177e4SLinus Torvalds * too long an error code of -EINVAL is returned. If the copy gives 1871da177e4SLinus Torvalds * invalid addresses -EFAULT is returned. On a success 0 is returned. 1881da177e4SLinus Torvalds */ 1891da177e4SLinus Torvalds 19043db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr) 1911da177e4SLinus Torvalds { 192230b1839SYOSHIFUJI Hideaki if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) 1931da177e4SLinus Torvalds return -EINVAL; 1941da177e4SLinus Torvalds if (ulen == 0) 1951da177e4SLinus Torvalds return 0; 1961da177e4SLinus Torvalds if (copy_from_user(kaddr, uaddr, ulen)) 1971da177e4SLinus Torvalds return -EFAULT; 1983ec3b2fbSDavid Woodhouse return audit_sockaddr(ulen, kaddr); 1991da177e4SLinus Torvalds } 2001da177e4SLinus Torvalds 2011da177e4SLinus Torvalds /** 2021da177e4SLinus Torvalds * move_addr_to_user - copy an address to user space 2031da177e4SLinus Torvalds * @kaddr: kernel space address 2041da177e4SLinus Torvalds * @klen: length of address in kernel 2051da177e4SLinus Torvalds * @uaddr: user space address 2061da177e4SLinus Torvalds * @ulen: pointer to user length field 2071da177e4SLinus Torvalds * 2081da177e4SLinus Torvalds * The value pointed to by ulen on entry is the buffer length available. 2091da177e4SLinus Torvalds * This is overwritten with the buffer space used. -EINVAL is returned 2101da177e4SLinus Torvalds * if an overlong buffer is specified or a negative buffer size. -EFAULT 2111da177e4SLinus Torvalds * is returned if either the buffer or the length field are not 2121da177e4SLinus Torvalds * accessible. 2131da177e4SLinus Torvalds * After copying the data up to the limit the user specifies, the true 2141da177e4SLinus Torvalds * length of the data is written over the length limit the user 2151da177e4SLinus Torvalds * specified. Zero is returned for a success. 2161da177e4SLinus Torvalds */ 2171da177e4SLinus Torvalds 21843db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, 21911165f14Sstephen hemminger void __user *uaddr, int __user *ulen) 2201da177e4SLinus Torvalds { 2211da177e4SLinus Torvalds int err; 2221da177e4SLinus Torvalds int len; 2231da177e4SLinus Torvalds 22468c6beb3SHannes Frederic Sowa BUG_ON(klen > sizeof(struct sockaddr_storage)); 22589bddce5SStephen Hemminger err = get_user(len, ulen); 22689bddce5SStephen Hemminger if (err) 2271da177e4SLinus Torvalds return err; 2281da177e4SLinus Torvalds if (len > klen) 2291da177e4SLinus Torvalds len = klen; 23068c6beb3SHannes Frederic Sowa if (len < 0) 2311da177e4SLinus Torvalds return -EINVAL; 23289bddce5SStephen Hemminger if (len) { 233d6fe3945SSteve Grubb if (audit_sockaddr(klen, kaddr)) 234d6fe3945SSteve Grubb return -ENOMEM; 2351da177e4SLinus Torvalds if (copy_to_user(uaddr, kaddr, len)) 2361da177e4SLinus Torvalds return -EFAULT; 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds /* 2391da177e4SLinus Torvalds * "fromlen shall refer to the value before truncation.." 2401da177e4SLinus Torvalds * 1003.1g 2411da177e4SLinus Torvalds */ 2421da177e4SLinus Torvalds return __put_user(klen, ulen); 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds 245e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly; 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb) 2481da177e4SLinus Torvalds { 2491da177e4SLinus Torvalds struct socket_alloc *ei; 250eaefd110SEric Dumazet struct socket_wq *wq; 25189bddce5SStephen Hemminger 252e94b1766SChristoph Lameter ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 2531da177e4SLinus Torvalds if (!ei) 2541da177e4SLinus Torvalds return NULL; 255eaefd110SEric Dumazet wq = kmalloc(sizeof(*wq), GFP_KERNEL); 256eaefd110SEric Dumazet if (!wq) { 25743815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 25843815482SEric Dumazet return NULL; 25943815482SEric Dumazet } 260eaefd110SEric Dumazet init_waitqueue_head(&wq->wait); 261eaefd110SEric Dumazet wq->fasync_list = NULL; 262eaefd110SEric Dumazet RCU_INIT_POINTER(ei->socket.wq, wq); 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds ei->socket.state = SS_UNCONNECTED; 2651da177e4SLinus Torvalds ei->socket.flags = 0; 2661da177e4SLinus Torvalds ei->socket.ops = NULL; 2671da177e4SLinus Torvalds ei->socket.sk = NULL; 2681da177e4SLinus Torvalds ei->socket.file = NULL; 2691da177e4SLinus Torvalds 2701da177e4SLinus Torvalds return &ei->vfs_inode; 2711da177e4SLinus Torvalds } 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode) 2741da177e4SLinus Torvalds { 27543815482SEric Dumazet struct socket_alloc *ei; 276eaefd110SEric Dumazet struct socket_wq *wq; 27743815482SEric Dumazet 27843815482SEric Dumazet ei = container_of(inode, struct socket_alloc, vfs_inode); 279eaefd110SEric Dumazet wq = rcu_dereference_protected(ei->socket.wq, 1); 28061845220SLai Jiangshan kfree_rcu(wq, rcu); 28143815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds 28451cc5068SAlexey Dobriyan static void init_once(void *foo) 2851da177e4SLinus Torvalds { 2861da177e4SLinus Torvalds struct socket_alloc *ei = (struct socket_alloc *)foo; 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode); 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds static int init_inodecache(void) 2921da177e4SLinus Torvalds { 2931da177e4SLinus Torvalds sock_inode_cachep = kmem_cache_create("sock_inode_cache", 2941da177e4SLinus Torvalds sizeof(struct socket_alloc), 29589bddce5SStephen Hemminger 0, 29689bddce5SStephen Hemminger (SLAB_HWCACHE_ALIGN | 29789bddce5SStephen Hemminger SLAB_RECLAIM_ACCOUNT | 298fffb60f9SPaul Jackson SLAB_MEM_SPREAD), 29920c2df83SPaul Mundt init_once); 3001da177e4SLinus Torvalds if (sock_inode_cachep == NULL) 3011da177e4SLinus Torvalds return -ENOMEM; 3021da177e4SLinus Torvalds return 0; 3031da177e4SLinus Torvalds } 3041da177e4SLinus Torvalds 305b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = { 3061da177e4SLinus Torvalds .alloc_inode = sock_alloc_inode, 3071da177e4SLinus Torvalds .destroy_inode = sock_destroy_inode, 3081da177e4SLinus Torvalds .statfs = simple_statfs, 3091da177e4SLinus Torvalds }; 3101da177e4SLinus Torvalds 311c23fbb6bSEric Dumazet /* 312c23fbb6bSEric Dumazet * sockfs_dname() is called from d_path(). 313c23fbb6bSEric Dumazet */ 314c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) 315c23fbb6bSEric Dumazet { 316c23fbb6bSEric Dumazet return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", 317c23fbb6bSEric Dumazet dentry->d_inode->i_ino); 318c23fbb6bSEric Dumazet } 319c23fbb6bSEric Dumazet 3203ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = { 321c23fbb6bSEric Dumazet .d_dname = sockfs_dname, 3221da177e4SLinus Torvalds }; 3231da177e4SLinus Torvalds 324c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type, 325c74a1cbbSAl Viro int flags, const char *dev_name, void *data) 326c74a1cbbSAl Viro { 327c74a1cbbSAl Viro return mount_pseudo(fs_type, "socket:", &sockfs_ops, 328c74a1cbbSAl Viro &sockfs_dentry_operations, SOCKFS_MAGIC); 329c74a1cbbSAl Viro } 330c74a1cbbSAl Viro 331c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly; 332c74a1cbbSAl Viro 333c74a1cbbSAl Viro static struct file_system_type sock_fs_type = { 334c74a1cbbSAl Viro .name = "sockfs", 335c74a1cbbSAl Viro .mount = sockfs_mount, 336c74a1cbbSAl Viro .kill_sb = kill_anon_super, 337c74a1cbbSAl Viro }; 338c74a1cbbSAl Viro 3391da177e4SLinus Torvalds /* 3401da177e4SLinus Torvalds * Obtains the first available file descriptor and sets it up for use. 3411da177e4SLinus Torvalds * 34239d8c1b6SDavid S. Miller * These functions create file structures and maps them to fd space 34339d8c1b6SDavid S. Miller * of the current process. On success it returns file descriptor 3441da177e4SLinus Torvalds * and file struct implicitly stored in sock->file. 3451da177e4SLinus Torvalds * Note that another thread may close file descriptor before we return 3461da177e4SLinus Torvalds * from this function. We use the fact that now we do not refer 3471da177e4SLinus Torvalds * to socket after mapping. If one day we will need it, this 3481da177e4SLinus Torvalds * function will increment ref. count on file by 1. 3491da177e4SLinus Torvalds * 3501da177e4SLinus Torvalds * In any case returned fd MAY BE not valid! 3511da177e4SLinus Torvalds * This race condition is unavoidable 3521da177e4SLinus Torvalds * with shared fd spaces, we cannot solve it inside kernel, 3531da177e4SLinus Torvalds * but we take care of internal coherence yet. 3541da177e4SLinus Torvalds */ 3551da177e4SLinus Torvalds 356aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) 3571da177e4SLinus Torvalds { 3587cbe66b6SAl Viro struct qstr name = { .name = "" }; 3592c48b9c4SAl Viro struct path path; 3607cbe66b6SAl Viro struct file *file; 3611da177e4SLinus Torvalds 362600e1779SMasatake YAMATO if (dname) { 363600e1779SMasatake YAMATO name.name = dname; 364600e1779SMasatake YAMATO name.len = strlen(name.name); 365600e1779SMasatake YAMATO } else if (sock->sk) { 366600e1779SMasatake YAMATO name.name = sock->sk->sk_prot_creator->name; 367600e1779SMasatake YAMATO name.len = strlen(name.name); 368600e1779SMasatake YAMATO } 3694b936885SNick Piggin path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); 37028407630SAl Viro if (unlikely(!path.dentry)) 37128407630SAl Viro return ERR_PTR(-ENOMEM); 3722c48b9c4SAl Viro path.mnt = mntget(sock_mnt); 37339d8c1b6SDavid S. Miller 3742c48b9c4SAl Viro d_instantiate(path.dentry, SOCK_INODE(sock)); 375cc3808f8SAl Viro 3762c48b9c4SAl Viro file = alloc_file(&path, FMODE_READ | FMODE_WRITE, 377cc3808f8SAl Viro &socket_file_ops); 37839b65252SAnatol Pomozov if (unlikely(IS_ERR(file))) { 379cc3808f8SAl Viro /* drop dentry, keep inode */ 3807de9c6eeSAl Viro ihold(path.dentry->d_inode); 3812c48b9c4SAl Viro path_put(&path); 38239b65252SAnatol Pomozov return file; 383cc3808f8SAl Viro } 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds sock->file = file; 38677d27200SUlrich Drepper file->f_flags = O_RDWR | (flags & O_NONBLOCK); 38707dc3f07SBenjamin LaHaise file->private_data = sock; 38828407630SAl Viro return file; 3891da177e4SLinus Torvalds } 39056b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file); 3911da177e4SLinus Torvalds 39256b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags) 39339d8c1b6SDavid S. Miller { 39439d8c1b6SDavid S. Miller struct file *newfile; 39528407630SAl Viro int fd = get_unused_fd_flags(flags); 39628407630SAl Viro if (unlikely(fd < 0)) 3971da177e4SLinus Torvalds return fd; 3981da177e4SLinus Torvalds 399aab174f0SLinus Torvalds newfile = sock_alloc_file(sock, flags, NULL); 40028407630SAl Viro if (likely(!IS_ERR(newfile))) { 4011da177e4SLinus Torvalds fd_install(fd, newfile); 4021da177e4SLinus Torvalds return fd; 4031da177e4SLinus Torvalds } 40428407630SAl Viro 40528407630SAl Viro put_unused_fd(fd); 40628407630SAl Viro return PTR_ERR(newfile); 4071da177e4SLinus Torvalds } 4081da177e4SLinus Torvalds 409406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err) 4106cb153caSBenjamin LaHaise { 4116cb153caSBenjamin LaHaise if (file->f_op == &socket_file_ops) 4126cb153caSBenjamin LaHaise return file->private_data; /* set in sock_map_fd */ 4136cb153caSBenjamin LaHaise 4146cb153caSBenjamin LaHaise *err = -ENOTSOCK; 4156cb153caSBenjamin LaHaise return NULL; 4166cb153caSBenjamin LaHaise } 417406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file); 4186cb153caSBenjamin LaHaise 4191da177e4SLinus Torvalds /** 4201da177e4SLinus Torvalds * sockfd_lookup - Go from a file number to its socket slot 4211da177e4SLinus Torvalds * @fd: file handle 4221da177e4SLinus Torvalds * @err: pointer to an error code return 4231da177e4SLinus Torvalds * 4241da177e4SLinus Torvalds * The file handle passed in is locked and the socket it is bound 4251da177e4SLinus Torvalds * too is returned. If an error occurs the err pointer is overwritten 4261da177e4SLinus Torvalds * with a negative errno code and NULL is returned. The function checks 4271da177e4SLinus Torvalds * for both invalid handles and passing a handle which is not a socket. 4281da177e4SLinus Torvalds * 4291da177e4SLinus Torvalds * On a success the socket object pointer is returned. 4301da177e4SLinus Torvalds */ 4311da177e4SLinus Torvalds 4321da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err) 4331da177e4SLinus Torvalds { 4341da177e4SLinus Torvalds struct file *file; 4351da177e4SLinus Torvalds struct socket *sock; 4361da177e4SLinus Torvalds 43789bddce5SStephen Hemminger file = fget(fd); 43889bddce5SStephen Hemminger if (!file) { 4391da177e4SLinus Torvalds *err = -EBADF; 4401da177e4SLinus Torvalds return NULL; 4411da177e4SLinus Torvalds } 44289bddce5SStephen Hemminger 4436cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4446cb153caSBenjamin LaHaise if (!sock) 4451da177e4SLinus Torvalds fput(file); 4466cb153caSBenjamin LaHaise return sock; 4471da177e4SLinus Torvalds } 448c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup); 4491da177e4SLinus Torvalds 4506cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) 4516cb153caSBenjamin LaHaise { 45200e188efSAl Viro struct fd f = fdget(fd); 4536cb153caSBenjamin LaHaise struct socket *sock; 4546cb153caSBenjamin LaHaise 4553672558cSHua Zhong *err = -EBADF; 45600e188efSAl Viro if (f.file) { 45700e188efSAl Viro sock = sock_from_file(f.file, err); 45800e188efSAl Viro if (likely(sock)) { 45900e188efSAl Viro *fput_needed = f.flags; 4601da177e4SLinus Torvalds return sock; 46100e188efSAl Viro } 46200e188efSAl Viro fdput(f); 4636cb153caSBenjamin LaHaise } 4646cb153caSBenjamin LaHaise return NULL; 4651da177e4SLinus Torvalds } 4661da177e4SLinus Torvalds 467600e1779SMasatake YAMATO #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname" 468600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX) 469600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1) 470600e1779SMasatake YAMATO static ssize_t sockfs_getxattr(struct dentry *dentry, 471600e1779SMasatake YAMATO const char *name, void *value, size_t size) 472600e1779SMasatake YAMATO { 473600e1779SMasatake YAMATO const char *proto_name; 474600e1779SMasatake YAMATO size_t proto_size; 475600e1779SMasatake YAMATO int error; 476600e1779SMasatake YAMATO 477600e1779SMasatake YAMATO error = -ENODATA; 478600e1779SMasatake YAMATO if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) { 479600e1779SMasatake YAMATO proto_name = dentry->d_name.name; 480600e1779SMasatake YAMATO proto_size = strlen(proto_name); 481600e1779SMasatake YAMATO 482600e1779SMasatake YAMATO if (value) { 483600e1779SMasatake YAMATO error = -ERANGE; 484600e1779SMasatake YAMATO if (proto_size + 1 > size) 485600e1779SMasatake YAMATO goto out; 486600e1779SMasatake YAMATO 487600e1779SMasatake YAMATO strncpy(value, proto_name, proto_size + 1); 488600e1779SMasatake YAMATO } 489600e1779SMasatake YAMATO error = proto_size + 1; 490600e1779SMasatake YAMATO } 491600e1779SMasatake YAMATO 492600e1779SMasatake YAMATO out: 493600e1779SMasatake YAMATO return error; 494600e1779SMasatake YAMATO } 495600e1779SMasatake YAMATO 496600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, 497600e1779SMasatake YAMATO size_t size) 498600e1779SMasatake YAMATO { 499600e1779SMasatake YAMATO ssize_t len; 500600e1779SMasatake YAMATO ssize_t used = 0; 501600e1779SMasatake YAMATO 502600e1779SMasatake YAMATO len = security_inode_listsecurity(dentry->d_inode, buffer, size); 503600e1779SMasatake YAMATO if (len < 0) 504600e1779SMasatake YAMATO return len; 505600e1779SMasatake YAMATO used += len; 506600e1779SMasatake YAMATO if (buffer) { 507600e1779SMasatake YAMATO if (size < used) 508600e1779SMasatake YAMATO return -ERANGE; 509600e1779SMasatake YAMATO buffer += len; 510600e1779SMasatake YAMATO } 511600e1779SMasatake YAMATO 512600e1779SMasatake YAMATO len = (XATTR_NAME_SOCKPROTONAME_LEN + 1); 513600e1779SMasatake YAMATO used += len; 514600e1779SMasatake YAMATO if (buffer) { 515600e1779SMasatake YAMATO if (size < used) 516600e1779SMasatake YAMATO return -ERANGE; 517600e1779SMasatake YAMATO memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len); 518600e1779SMasatake YAMATO buffer += len; 519600e1779SMasatake YAMATO } 520600e1779SMasatake YAMATO 521600e1779SMasatake YAMATO return used; 522600e1779SMasatake YAMATO } 523600e1779SMasatake YAMATO 524600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = { 525600e1779SMasatake YAMATO .getxattr = sockfs_getxattr, 526600e1779SMasatake YAMATO .listxattr = sockfs_listxattr, 527600e1779SMasatake YAMATO }; 528600e1779SMasatake YAMATO 5291da177e4SLinus Torvalds /** 5301da177e4SLinus Torvalds * sock_alloc - allocate a socket 5311da177e4SLinus Torvalds * 5321da177e4SLinus Torvalds * Allocate a new inode and socket object. The two are bound together 5331da177e4SLinus Torvalds * and initialised. The socket is then returned. If we are out of inodes 5341da177e4SLinus Torvalds * NULL is returned. 5351da177e4SLinus Torvalds */ 5361da177e4SLinus Torvalds 5371da177e4SLinus Torvalds static struct socket *sock_alloc(void) 5381da177e4SLinus Torvalds { 5391da177e4SLinus Torvalds struct inode *inode; 5401da177e4SLinus Torvalds struct socket *sock; 5411da177e4SLinus Torvalds 542a209dfc7SEric Dumazet inode = new_inode_pseudo(sock_mnt->mnt_sb); 5431da177e4SLinus Torvalds if (!inode) 5441da177e4SLinus Torvalds return NULL; 5451da177e4SLinus Torvalds 5461da177e4SLinus Torvalds sock = SOCKET_I(inode); 5471da177e4SLinus Torvalds 54829a020d3SEric Dumazet kmemcheck_annotate_bitfield(sock, type); 54985fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 5501da177e4SLinus Torvalds inode->i_mode = S_IFSOCK | S_IRWXUGO; 5518192b0c4SDavid Howells inode->i_uid = current_fsuid(); 5528192b0c4SDavid Howells inode->i_gid = current_fsgid(); 553600e1779SMasatake YAMATO inode->i_op = &sockfs_inode_ops; 5541da177e4SLinus Torvalds 55519e8d69cSAlex Shi this_cpu_add(sockets_in_use, 1); 5561da177e4SLinus Torvalds return sock; 5571da177e4SLinus Torvalds } 5581da177e4SLinus Torvalds 5591da177e4SLinus Torvalds /** 5601da177e4SLinus Torvalds * sock_release - close a socket 5611da177e4SLinus Torvalds * @sock: socket to close 5621da177e4SLinus Torvalds * 5631da177e4SLinus Torvalds * The socket is released from the protocol stack if it has a release 5641da177e4SLinus Torvalds * callback, and the inode is then released if the socket is bound to 5651da177e4SLinus Torvalds * an inode not a file. 5661da177e4SLinus Torvalds */ 5671da177e4SLinus Torvalds 5681da177e4SLinus Torvalds void sock_release(struct socket *sock) 5691da177e4SLinus Torvalds { 5701da177e4SLinus Torvalds if (sock->ops) { 5711da177e4SLinus Torvalds struct module *owner = sock->ops->owner; 5721da177e4SLinus Torvalds 5731da177e4SLinus Torvalds sock->ops->release(sock); 5741da177e4SLinus Torvalds sock->ops = NULL; 5751da177e4SLinus Torvalds module_put(owner); 5761da177e4SLinus Torvalds } 5771da177e4SLinus Torvalds 578eaefd110SEric Dumazet if (rcu_dereference_protected(sock->wq, 1)->fasync_list) 5793410f22eSYang Yingliang pr_err("%s: fasync list not empty!\n", __func__); 5801da177e4SLinus Torvalds 581b09e786bSMikulas Patocka if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags)) 582b09e786bSMikulas Patocka return; 583b09e786bSMikulas Patocka 58419e8d69cSAlex Shi this_cpu_sub(sockets_in_use, 1); 5851da177e4SLinus Torvalds if (!sock->file) { 5861da177e4SLinus Torvalds iput(SOCK_INODE(sock)); 5871da177e4SLinus Torvalds return; 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds sock->file = NULL; 5901da177e4SLinus Torvalds } 591c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release); 5921da177e4SLinus Torvalds 59367cc0d40SWillem de Bruijn void __sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags) 59420d49473SPatrick Ohly { 595140c55d4SEric Dumazet u8 flags = *tx_flags; 596140c55d4SEric Dumazet 597b9f40e21SWillem de Bruijn if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE) 598140c55d4SEric Dumazet flags |= SKBTX_HW_TSTAMP; 599140c55d4SEric Dumazet 600b9f40e21SWillem de Bruijn if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) 601140c55d4SEric Dumazet flags |= SKBTX_SW_TSTAMP; 602140c55d4SEric Dumazet 603e7fd2885SWillem de Bruijn if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED) 604140c55d4SEric Dumazet flags |= SKBTX_SCHED_TSTAMP; 605140c55d4SEric Dumazet 606e1c8a607SWillem de Bruijn if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK) 607140c55d4SEric Dumazet flags |= SKBTX_ACK_TSTAMP; 608e7fd2885SWillem de Bruijn 609140c55d4SEric Dumazet *tx_flags = flags; 61020d49473SPatrick Ohly } 61167cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp); 61220d49473SPatrick Ohly 613228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock, 6141da177e4SLinus Torvalds struct msghdr *msg, size_t size) 6151da177e4SLinus Torvalds { 6161da177e4SLinus Torvalds return sock->ops->sendmsg(iocb, sock, msg, size); 6171da177e4SLinus Torvalds } 6181da177e4SLinus Torvalds 619228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, 620228e548eSAnton Blanchard struct msghdr *msg, size_t size) 621228e548eSAnton Blanchard { 622228e548eSAnton Blanchard int err = security_socket_sendmsg(sock, msg, size); 623228e548eSAnton Blanchard 624228e548eSAnton Blanchard return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size); 625228e548eSAnton Blanchard } 626228e548eSAnton Blanchard 6270cf00c6fSGu Zheng static int do_sock_sendmsg(struct socket *sock, struct msghdr *msg, 6280cf00c6fSGu Zheng size_t size, bool nosec) 6291da177e4SLinus Torvalds { 6301da177e4SLinus Torvalds struct kiocb iocb; 6311da177e4SLinus Torvalds int ret; 6321da177e4SLinus Torvalds 6331da177e4SLinus Torvalds init_sync_kiocb(&iocb, NULL); 6340cf00c6fSGu Zheng ret = nosec ? __sock_sendmsg_nosec(&iocb, sock, msg, size) : 6350cf00c6fSGu Zheng __sock_sendmsg(&iocb, sock, msg, size); 6361da177e4SLinus Torvalds if (-EIOCBQUEUED == ret) 6371da177e4SLinus Torvalds ret = wait_on_sync_kiocb(&iocb); 6381da177e4SLinus Torvalds return ret; 6391da177e4SLinus Torvalds } 6400cf00c6fSGu Zheng 6410cf00c6fSGu Zheng int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) 6420cf00c6fSGu Zheng { 6430cf00c6fSGu Zheng return do_sock_sendmsg(sock, msg, size, false); 6440cf00c6fSGu Zheng } 645c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg); 6461da177e4SLinus Torvalds 647894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size) 648228e548eSAnton Blanchard { 6490cf00c6fSGu Zheng return do_sock_sendmsg(sock, msg, size, true); 650228e548eSAnton Blanchard } 651228e548eSAnton Blanchard 6521da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg, 6531da177e4SLinus Torvalds struct kvec *vec, size_t num, size_t size) 6541da177e4SLinus Torvalds { 6551da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 6561da177e4SLinus Torvalds int result; 6571da177e4SLinus Torvalds 6581da177e4SLinus Torvalds set_fs(KERNEL_DS); 6591da177e4SLinus Torvalds /* 6601da177e4SLinus Torvalds * the following is safe, since for compiler definitions of kvec and 6611da177e4SLinus Torvalds * iovec are identical, yielding the same in-core layout and alignment 6621da177e4SLinus Torvalds */ 663c0371da6SAl Viro iov_iter_init(&msg->msg_iter, WRITE, (struct iovec *)vec, num, size); 6641da177e4SLinus Torvalds result = sock_sendmsg(sock, msg, size); 6651da177e4SLinus Torvalds set_fs(oldfs); 6661da177e4SLinus Torvalds return result; 6671da177e4SLinus Torvalds } 668c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg); 6691da177e4SLinus Torvalds 67092f37fd2SEric Dumazet /* 67192f37fd2SEric Dumazet * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) 67292f37fd2SEric Dumazet */ 67392f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 67492f37fd2SEric Dumazet struct sk_buff *skb) 67592f37fd2SEric Dumazet { 67620d49473SPatrick Ohly int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 677f24b9be5SWillem de Bruijn struct scm_timestamping tss; 67820d49473SPatrick Ohly int empty = 1; 67920d49473SPatrick Ohly struct skb_shared_hwtstamps *shhwtstamps = 68020d49473SPatrick Ohly skb_hwtstamps(skb); 68192f37fd2SEric Dumazet 68220d49473SPatrick Ohly /* Race occurred between timestamp enabling and packet 68320d49473SPatrick Ohly receiving. Fill in the current time for now. */ 68420d49473SPatrick Ohly if (need_software_tstamp && skb->tstamp.tv64 == 0) 68520d49473SPatrick Ohly __net_timestamp(skb); 68620d49473SPatrick Ohly 68720d49473SPatrick Ohly if (need_software_tstamp) { 68892f37fd2SEric Dumazet if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { 68992f37fd2SEric Dumazet struct timeval tv; 69020d49473SPatrick Ohly skb_get_timestamp(skb, &tv); 69120d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, 69220d49473SPatrick Ohly sizeof(tv), &tv); 69392f37fd2SEric Dumazet } else { 694f24b9be5SWillem de Bruijn struct timespec ts; 695f24b9be5SWillem de Bruijn skb_get_timestampns(skb, &ts); 69620d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, 697f24b9be5SWillem de Bruijn sizeof(ts), &ts); 69892f37fd2SEric Dumazet } 69992f37fd2SEric Dumazet } 70092f37fd2SEric Dumazet 701f24b9be5SWillem de Bruijn memset(&tss, 0, sizeof(tss)); 702c199105dSWillem de Bruijn if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && 703f24b9be5SWillem de Bruijn ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) 70420d49473SPatrick Ohly empty = 0; 7054d276eb6SWillem de Bruijn if (shhwtstamps && 706b9f40e21SWillem de Bruijn (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && 707f24b9be5SWillem de Bruijn ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) 70820d49473SPatrick Ohly empty = 0; 70920d49473SPatrick Ohly if (!empty) 71020d49473SPatrick Ohly put_cmsg(msg, SOL_SOCKET, 711f24b9be5SWillem de Bruijn SCM_TIMESTAMPING, sizeof(tss), &tss); 71220d49473SPatrick Ohly } 7137c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 7147c81fd8bSArnaldo Carvalho de Melo 7156e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, 7166e3e939fSJohannes Berg struct sk_buff *skb) 7176e3e939fSJohannes Berg { 7186e3e939fSJohannes Berg int ack; 7196e3e939fSJohannes Berg 7206e3e939fSJohannes Berg if (!sock_flag(sk, SOCK_WIFI_STATUS)) 7216e3e939fSJohannes Berg return; 7226e3e939fSJohannes Berg if (!skb->wifi_acked_valid) 7236e3e939fSJohannes Berg return; 7246e3e939fSJohannes Berg 7256e3e939fSJohannes Berg ack = skb->wifi_acked; 7266e3e939fSJohannes Berg 7276e3e939fSJohannes Berg put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack); 7286e3e939fSJohannes Berg } 7296e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status); 7306e3e939fSJohannes Berg 73111165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, 73211165f14Sstephen hemminger struct sk_buff *skb) 7333b885787SNeil Horman { 7343b885787SNeil Horman if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount) 7353b885787SNeil Horman put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, 7363b885787SNeil Horman sizeof(__u32), &skb->dropcount); 7373b885787SNeil Horman } 7383b885787SNeil Horman 739767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 7403b885787SNeil Horman struct sk_buff *skb) 7413b885787SNeil Horman { 7423b885787SNeil Horman sock_recv_timestamp(msg, sk, skb); 7433b885787SNeil Horman sock_recv_drops(msg, sk, skb); 7443b885787SNeil Horman } 745767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); 7463b885787SNeil Horman 747a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, 7481da177e4SLinus Torvalds struct msghdr *msg, size_t size, int flags) 7491da177e4SLinus Torvalds { 7501da177e4SLinus Torvalds return sock->ops->recvmsg(iocb, sock, msg, size, flags); 7511da177e4SLinus Torvalds } 7521da177e4SLinus Torvalds 753a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, 754a2e27255SArnaldo Carvalho de Melo struct msghdr *msg, size_t size, int flags) 755a2e27255SArnaldo Carvalho de Melo { 756a2e27255SArnaldo Carvalho de Melo int err = security_socket_recvmsg(sock, msg, size, flags); 757a2e27255SArnaldo Carvalho de Melo 758a2e27255SArnaldo Carvalho de Melo return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags); 759a2e27255SArnaldo Carvalho de Melo } 760a2e27255SArnaldo Carvalho de Melo 7611da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg, 7621da177e4SLinus Torvalds size_t size, int flags) 7631da177e4SLinus Torvalds { 7641da177e4SLinus Torvalds struct kiocb iocb; 7651da177e4SLinus Torvalds int ret; 7661da177e4SLinus Torvalds 7671da177e4SLinus Torvalds init_sync_kiocb(&iocb, NULL); 7681da177e4SLinus Torvalds ret = __sock_recvmsg(&iocb, sock, msg, size, flags); 7691da177e4SLinus Torvalds if (-EIOCBQUEUED == ret) 7701da177e4SLinus Torvalds ret = wait_on_sync_kiocb(&iocb); 7711da177e4SLinus Torvalds return ret; 7721da177e4SLinus Torvalds } 773c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg); 7741da177e4SLinus Torvalds 775a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, 776a2e27255SArnaldo Carvalho de Melo size_t size, int flags) 777a2e27255SArnaldo Carvalho de Melo { 778a2e27255SArnaldo Carvalho de Melo struct kiocb iocb; 779a2e27255SArnaldo Carvalho de Melo int ret; 780a2e27255SArnaldo Carvalho de Melo 781a2e27255SArnaldo Carvalho de Melo init_sync_kiocb(&iocb, NULL); 782a2e27255SArnaldo Carvalho de Melo ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags); 783a2e27255SArnaldo Carvalho de Melo if (-EIOCBQUEUED == ret) 784a2e27255SArnaldo Carvalho de Melo ret = wait_on_sync_kiocb(&iocb); 785a2e27255SArnaldo Carvalho de Melo return ret; 786a2e27255SArnaldo Carvalho de Melo } 787a2e27255SArnaldo Carvalho de Melo 788c1249c0aSMartin Lucina /** 789c1249c0aSMartin Lucina * kernel_recvmsg - Receive a message from a socket (kernel space) 790c1249c0aSMartin Lucina * @sock: The socket to receive the message from 791c1249c0aSMartin Lucina * @msg: Received message 792c1249c0aSMartin Lucina * @vec: Input s/g array for message data 793c1249c0aSMartin Lucina * @num: Size of input s/g array 794c1249c0aSMartin Lucina * @size: Number of bytes to read 795c1249c0aSMartin Lucina * @flags: Message flags (MSG_DONTWAIT, etc...) 796c1249c0aSMartin Lucina * 797c1249c0aSMartin Lucina * On return the msg structure contains the scatter/gather array passed in the 798c1249c0aSMartin Lucina * vec argument. The array is modified so that it consists of the unfilled 799c1249c0aSMartin Lucina * portion of the original array. 800c1249c0aSMartin Lucina * 801c1249c0aSMartin Lucina * The returned value is the total number of bytes received, or an error. 802c1249c0aSMartin Lucina */ 8031da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg, 80489bddce5SStephen Hemminger struct kvec *vec, size_t num, size_t size, int flags) 8051da177e4SLinus Torvalds { 8061da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 8071da177e4SLinus Torvalds int result; 8081da177e4SLinus Torvalds 8091da177e4SLinus Torvalds set_fs(KERNEL_DS); 8101da177e4SLinus Torvalds /* 8111da177e4SLinus Torvalds * the following is safe, since for compiler definitions of kvec and 8121da177e4SLinus Torvalds * iovec are identical, yielding the same in-core layout and alignment 8131da177e4SLinus Torvalds */ 814c0371da6SAl Viro iov_iter_init(&msg->msg_iter, READ, (struct iovec *)vec, num, size); 8151da177e4SLinus Torvalds result = sock_recvmsg(sock, msg, size, flags); 8161da177e4SLinus Torvalds set_fs(oldfs); 8171da177e4SLinus Torvalds return result; 8181da177e4SLinus Torvalds } 819c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg); 8201da177e4SLinus Torvalds 82120380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page, 8221da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more) 8231da177e4SLinus Torvalds { 8241da177e4SLinus Torvalds struct socket *sock; 8251da177e4SLinus Torvalds int flags; 8261da177e4SLinus Torvalds 827b69aee04SEric Dumazet sock = file->private_data; 8281da177e4SLinus Torvalds 82935f9c09fSEric Dumazet flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 83035f9c09fSEric Dumazet /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */ 83135f9c09fSEric Dumazet flags |= more; 8321da177e4SLinus Torvalds 833e6949583SLinus Torvalds return kernel_sendpage(sock, page, offset, size, flags); 8341da177e4SLinus Torvalds } 8351da177e4SLinus Torvalds 8369c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 8379c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 8389c55e01cSJens Axboe unsigned int flags) 8399c55e01cSJens Axboe { 8409c55e01cSJens Axboe struct socket *sock = file->private_data; 8419c55e01cSJens Axboe 842997b37daSRémi Denis-Courmont if (unlikely(!sock->ops->splice_read)) 843997b37daSRémi Denis-Courmont return -EINVAL; 844997b37daSRémi Denis-Courmont 8459c55e01cSJens Axboe return sock->ops->splice_read(sock, ppos, pipe, len, flags); 8469c55e01cSJens Axboe } 8479c55e01cSJens Axboe 848*8ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to) 849ce1d4d3eSChristoph Hellwig { 8506d652330SAl Viro struct file *file = iocb->ki_filp; 8516d652330SAl Viro struct socket *sock = file->private_data; 852*8ae5e030SAl Viro struct msghdr msg = {.msg_iter = *to}; 853*8ae5e030SAl Viro ssize_t res; 854ce1d4d3eSChristoph Hellwig 855*8ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 856*8ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 857*8ae5e030SAl Viro 858*8ae5e030SAl Viro if (iocb->ki_pos != 0) 859ce1d4d3eSChristoph Hellwig return -ESPIPE; 860027445c3SBadari Pulavarty 86173a7075eSKent Overstreet if (iocb->ki_nbytes == 0) /* Match SYS5 behaviour */ 862ce1d4d3eSChristoph Hellwig return 0; 863ce1d4d3eSChristoph Hellwig 864*8ae5e030SAl Viro res = __sock_recvmsg(iocb, sock, &msg, 865*8ae5e030SAl Viro iocb->ki_nbytes, msg.msg_flags); 866*8ae5e030SAl Viro *to = msg.msg_iter; 867*8ae5e030SAl Viro return res; 868ce1d4d3eSChristoph Hellwig } 869ce1d4d3eSChristoph Hellwig 870*8ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) 8711da177e4SLinus Torvalds { 8726d652330SAl Viro struct file *file = iocb->ki_filp; 8736d652330SAl Viro struct socket *sock = file->private_data; 874*8ae5e030SAl Viro struct msghdr msg = {.msg_iter = *from}; 875*8ae5e030SAl Viro ssize_t res; 8761da177e4SLinus Torvalds 877*8ae5e030SAl Viro if (iocb->ki_pos != 0) 878ce1d4d3eSChristoph Hellwig return -ESPIPE; 879027445c3SBadari Pulavarty 880*8ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 881*8ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 882*8ae5e030SAl Viro 8836d652330SAl Viro if (sock->type == SOCK_SEQPACKET) 8846d652330SAl Viro msg.msg_flags |= MSG_EOR; 8856d652330SAl Viro 886*8ae5e030SAl Viro res = __sock_sendmsg(iocb, sock, &msg, iocb->ki_nbytes); 887*8ae5e030SAl Viro *from = msg.msg_iter; 888*8ae5e030SAl Viro return res; 8891da177e4SLinus Torvalds } 8901da177e4SLinus Torvalds 8911da177e4SLinus Torvalds /* 8921da177e4SLinus Torvalds * Atomic setting of ioctl hooks to avoid race 8931da177e4SLinus Torvalds * with module unload. 8941da177e4SLinus Torvalds */ 8951da177e4SLinus Torvalds 8964a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex); 897c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg); 8981da177e4SLinus Torvalds 899881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *)) 9001da177e4SLinus Torvalds { 9014a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 9021da177e4SLinus Torvalds br_ioctl_hook = hook; 9034a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 9041da177e4SLinus Torvalds } 9051da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set); 9061da177e4SLinus Torvalds 9074a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex); 908881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg); 9091da177e4SLinus Torvalds 910881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *)) 9111da177e4SLinus Torvalds { 9124a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 9131da177e4SLinus Torvalds vlan_ioctl_hook = hook; 9144a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 9151da177e4SLinus Torvalds } 9161da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set); 9171da177e4SLinus Torvalds 9184a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex); 9191da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *); 9201da177e4SLinus Torvalds 9211da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) 9221da177e4SLinus Torvalds { 9234a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 9241da177e4SLinus Torvalds dlci_ioctl_hook = hook; 9254a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 9261da177e4SLinus Torvalds } 9271da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set); 9281da177e4SLinus Torvalds 9296b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock, 9306b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 9316b96018bSArnd Bergmann { 9326b96018bSArnd Bergmann int err; 9336b96018bSArnd Bergmann void __user *argp = (void __user *)arg; 9346b96018bSArnd Bergmann 9356b96018bSArnd Bergmann err = sock->ops->ioctl(sock, cmd, arg); 9366b96018bSArnd Bergmann 9376b96018bSArnd Bergmann /* 9386b96018bSArnd Bergmann * If this ioctl is unknown try to hand it down 9396b96018bSArnd Bergmann * to the NIC driver. 9406b96018bSArnd Bergmann */ 9416b96018bSArnd Bergmann if (err == -ENOIOCTLCMD) 9426b96018bSArnd Bergmann err = dev_ioctl(net, cmd, argp); 9436b96018bSArnd Bergmann 9446b96018bSArnd Bergmann return err; 9456b96018bSArnd Bergmann } 9466b96018bSArnd Bergmann 9471da177e4SLinus Torvalds /* 9481da177e4SLinus Torvalds * With an ioctl, arg may well be a user mode pointer, but we don't know 9491da177e4SLinus Torvalds * what to do with it - that's up to the protocol still. 9501da177e4SLinus Torvalds */ 9511da177e4SLinus Torvalds 9521da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) 9531da177e4SLinus Torvalds { 9541da177e4SLinus Torvalds struct socket *sock; 955881d966bSEric W. Biederman struct sock *sk; 9561da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 9571da177e4SLinus Torvalds int pid, err; 958881d966bSEric W. Biederman struct net *net; 9591da177e4SLinus Torvalds 960b69aee04SEric Dumazet sock = file->private_data; 961881d966bSEric W. Biederman sk = sock->sk; 9623b1e0a65SYOSHIFUJI Hideaki net = sock_net(sk); 9631da177e4SLinus Torvalds if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { 964881d966bSEric W. Biederman err = dev_ioctl(net, cmd, argp); 9651da177e4SLinus Torvalds } else 9663d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE 9671da177e4SLinus Torvalds if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { 968881d966bSEric W. Biederman err = dev_ioctl(net, cmd, argp); 9691da177e4SLinus Torvalds } else 9703d23e349SJohannes Berg #endif 9711da177e4SLinus Torvalds switch (cmd) { 9721da177e4SLinus Torvalds case FIOSETOWN: 9731da177e4SLinus Torvalds case SIOCSPGRP: 9741da177e4SLinus Torvalds err = -EFAULT; 9751da177e4SLinus Torvalds if (get_user(pid, (int __user *)argp)) 9761da177e4SLinus Torvalds break; 977e0b93eddSJeff Layton f_setown(sock->file, pid, 1); 978e0b93eddSJeff Layton err = 0; 9791da177e4SLinus Torvalds break; 9801da177e4SLinus Torvalds case FIOGETOWN: 9811da177e4SLinus Torvalds case SIOCGPGRP: 982609d7fa9SEric W. Biederman err = put_user(f_getown(sock->file), 98389bddce5SStephen Hemminger (int __user *)argp); 9841da177e4SLinus Torvalds break; 9851da177e4SLinus Torvalds case SIOCGIFBR: 9861da177e4SLinus Torvalds case SIOCSIFBR: 9871da177e4SLinus Torvalds case SIOCBRADDBR: 9881da177e4SLinus Torvalds case SIOCBRDELBR: 9891da177e4SLinus Torvalds err = -ENOPKG; 9901da177e4SLinus Torvalds if (!br_ioctl_hook) 9911da177e4SLinus Torvalds request_module("bridge"); 9921da177e4SLinus Torvalds 9934a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 9941da177e4SLinus Torvalds if (br_ioctl_hook) 995881d966bSEric W. Biederman err = br_ioctl_hook(net, cmd, argp); 9964a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 9971da177e4SLinus Torvalds break; 9981da177e4SLinus Torvalds case SIOCGIFVLAN: 9991da177e4SLinus Torvalds case SIOCSIFVLAN: 10001da177e4SLinus Torvalds err = -ENOPKG; 10011da177e4SLinus Torvalds if (!vlan_ioctl_hook) 10021da177e4SLinus Torvalds request_module("8021q"); 10031da177e4SLinus Torvalds 10044a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 10051da177e4SLinus Torvalds if (vlan_ioctl_hook) 1006881d966bSEric W. Biederman err = vlan_ioctl_hook(net, argp); 10074a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 10081da177e4SLinus Torvalds break; 10091da177e4SLinus Torvalds case SIOCADDDLCI: 10101da177e4SLinus Torvalds case SIOCDELDLCI: 10111da177e4SLinus Torvalds err = -ENOPKG; 10121da177e4SLinus Torvalds if (!dlci_ioctl_hook) 10131da177e4SLinus Torvalds request_module("dlci"); 10141da177e4SLinus Torvalds 10154a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 10167512cbf6SPavel Emelyanov if (dlci_ioctl_hook) 10171da177e4SLinus Torvalds err = dlci_ioctl_hook(cmd, argp); 10184a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 10191da177e4SLinus Torvalds break; 10201da177e4SLinus Torvalds default: 10216b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, arg); 10221da177e4SLinus Torvalds break; 10231da177e4SLinus Torvalds } 10241da177e4SLinus Torvalds return err; 10251da177e4SLinus Torvalds } 10261da177e4SLinus Torvalds 10271da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res) 10281da177e4SLinus Torvalds { 10291da177e4SLinus Torvalds int err; 10301da177e4SLinus Torvalds struct socket *sock = NULL; 10311da177e4SLinus Torvalds 10321da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, 1); 10331da177e4SLinus Torvalds if (err) 10341da177e4SLinus Torvalds goto out; 10351da177e4SLinus Torvalds 10361da177e4SLinus Torvalds sock = sock_alloc(); 10371da177e4SLinus Torvalds if (!sock) { 10381da177e4SLinus Torvalds err = -ENOMEM; 10391da177e4SLinus Torvalds goto out; 10401da177e4SLinus Torvalds } 10411da177e4SLinus Torvalds 10421da177e4SLinus Torvalds sock->type = type; 10437420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, 1); 10447420ed23SVenkat Yekkirala if (err) 10457420ed23SVenkat Yekkirala goto out_release; 10467420ed23SVenkat Yekkirala 10471da177e4SLinus Torvalds out: 10481da177e4SLinus Torvalds *res = sock; 10491da177e4SLinus Torvalds return err; 10507420ed23SVenkat Yekkirala out_release: 10517420ed23SVenkat Yekkirala sock_release(sock); 10527420ed23SVenkat Yekkirala sock = NULL; 10537420ed23SVenkat Yekkirala goto out; 10541da177e4SLinus Torvalds } 1055c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite); 10561da177e4SLinus Torvalds 10571da177e4SLinus Torvalds /* No kernel lock held - perfect */ 10581da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait) 10591da177e4SLinus Torvalds { 1060cbf55001SEliezer Tamir unsigned int busy_flag = 0; 10611da177e4SLinus Torvalds struct socket *sock; 10621da177e4SLinus Torvalds 10631da177e4SLinus Torvalds /* 10641da177e4SLinus Torvalds * We can't return errors to poll, so it's either yes or no. 10651da177e4SLinus Torvalds */ 1066b69aee04SEric Dumazet sock = file->private_data; 10672d48d67fSEliezer Tamir 1068cbf55001SEliezer Tamir if (sk_can_busy_loop(sock->sk)) { 10692d48d67fSEliezer Tamir /* this socket can poll_ll so tell the system call */ 1070cbf55001SEliezer Tamir busy_flag = POLL_BUSY_LOOP; 10712d48d67fSEliezer Tamir 10722d48d67fSEliezer Tamir /* once, only if requested by syscall */ 1073cbf55001SEliezer Tamir if (wait && (wait->_key & POLL_BUSY_LOOP)) 1074cbf55001SEliezer Tamir sk_busy_loop(sock->sk, 1); 10752d48d67fSEliezer Tamir } 10762d48d67fSEliezer Tamir 1077cbf55001SEliezer Tamir return busy_flag | sock->ops->poll(file, sock, wait); 10781da177e4SLinus Torvalds } 10791da177e4SLinus Torvalds 10801da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma) 10811da177e4SLinus Torvalds { 1082b69aee04SEric Dumazet struct socket *sock = file->private_data; 10831da177e4SLinus Torvalds 10841da177e4SLinus Torvalds return sock->ops->mmap(file, sock, vma); 10851da177e4SLinus Torvalds } 10861da177e4SLinus Torvalds 108720380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp) 10881da177e4SLinus Torvalds { 10891da177e4SLinus Torvalds sock_release(SOCKET_I(inode)); 10901da177e4SLinus Torvalds return 0; 10911da177e4SLinus Torvalds } 10921da177e4SLinus Torvalds 10931da177e4SLinus Torvalds /* 10941da177e4SLinus Torvalds * Update the socket async list 10951da177e4SLinus Torvalds * 10961da177e4SLinus Torvalds * Fasync_list locking strategy. 10971da177e4SLinus Torvalds * 10981da177e4SLinus Torvalds * 1. fasync_list is modified only under process context socket lock 10991da177e4SLinus Torvalds * i.e. under semaphore. 11001da177e4SLinus Torvalds * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1101989a2979SEric Dumazet * or under socket lock 11021da177e4SLinus Torvalds */ 11031da177e4SLinus Torvalds 11041da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on) 11051da177e4SLinus Torvalds { 1106989a2979SEric Dumazet struct socket *sock = filp->private_data; 1107989a2979SEric Dumazet struct sock *sk = sock->sk; 1108eaefd110SEric Dumazet struct socket_wq *wq; 11091da177e4SLinus Torvalds 1110989a2979SEric Dumazet if (sk == NULL) 11111da177e4SLinus Torvalds return -EINVAL; 11121da177e4SLinus Torvalds 11131da177e4SLinus Torvalds lock_sock(sk); 1114eaefd110SEric Dumazet wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk)); 1115eaefd110SEric Dumazet fasync_helper(fd, filp, on, &wq->fasync_list); 11161da177e4SLinus Torvalds 1117eaefd110SEric Dumazet if (!wq->fasync_list) 1118bcdce719SEric Dumazet sock_reset_flag(sk, SOCK_FASYNC); 1119989a2979SEric Dumazet else 1120989a2979SEric Dumazet sock_set_flag(sk, SOCK_FASYNC); 11211da177e4SLinus Torvalds 1122989a2979SEric Dumazet release_sock(sk); 11231da177e4SLinus Torvalds return 0; 11241da177e4SLinus Torvalds } 11251da177e4SLinus Torvalds 112643815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */ 11271da177e4SLinus Torvalds 11281da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band) 11291da177e4SLinus Torvalds { 113043815482SEric Dumazet struct socket_wq *wq; 113143815482SEric Dumazet 113243815482SEric Dumazet if (!sock) 11331da177e4SLinus Torvalds return -1; 113443815482SEric Dumazet rcu_read_lock(); 113543815482SEric Dumazet wq = rcu_dereference(sock->wq); 113643815482SEric Dumazet if (!wq || !wq->fasync_list) { 113743815482SEric Dumazet rcu_read_unlock(); 113843815482SEric Dumazet return -1; 113943815482SEric Dumazet } 114089bddce5SStephen Hemminger switch (how) { 11418d8ad9d7SPavel Emelyanov case SOCK_WAKE_WAITD: 11421da177e4SLinus Torvalds if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) 11431da177e4SLinus Torvalds break; 11441da177e4SLinus Torvalds goto call_kill; 11458d8ad9d7SPavel Emelyanov case SOCK_WAKE_SPACE: 11461da177e4SLinus Torvalds if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags)) 11471da177e4SLinus Torvalds break; 11481da177e4SLinus Torvalds /* fall through */ 11498d8ad9d7SPavel Emelyanov case SOCK_WAKE_IO: 11501da177e4SLinus Torvalds call_kill: 115143815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGIO, band); 11521da177e4SLinus Torvalds break; 11538d8ad9d7SPavel Emelyanov case SOCK_WAKE_URG: 115443815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGURG, band); 11551da177e4SLinus Torvalds } 115643815482SEric Dumazet rcu_read_unlock(); 11571da177e4SLinus Torvalds return 0; 11581da177e4SLinus Torvalds } 1159c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async); 11601da177e4SLinus Torvalds 1161721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol, 116289bddce5SStephen Hemminger struct socket **res, int kern) 11631da177e4SLinus Torvalds { 11641da177e4SLinus Torvalds int err; 11651da177e4SLinus Torvalds struct socket *sock; 116655737fdaSStephen Hemminger const struct net_proto_family *pf; 11671da177e4SLinus Torvalds 11681da177e4SLinus Torvalds /* 11691da177e4SLinus Torvalds * Check protocol is in range 11701da177e4SLinus Torvalds */ 11711da177e4SLinus Torvalds if (family < 0 || family >= NPROTO) 11721da177e4SLinus Torvalds return -EAFNOSUPPORT; 11731da177e4SLinus Torvalds if (type < 0 || type >= SOCK_MAX) 11741da177e4SLinus Torvalds return -EINVAL; 11751da177e4SLinus Torvalds 11761da177e4SLinus Torvalds /* Compatibility. 11771da177e4SLinus Torvalds 11781da177e4SLinus Torvalds This uglymoron is moved from INET layer to here to avoid 11791da177e4SLinus Torvalds deadlock in module load. 11801da177e4SLinus Torvalds */ 11811da177e4SLinus Torvalds if (family == PF_INET && type == SOCK_PACKET) { 11821da177e4SLinus Torvalds static int warned; 11831da177e4SLinus Torvalds if (!warned) { 11841da177e4SLinus Torvalds warned = 1; 11853410f22eSYang Yingliang pr_info("%s uses obsolete (PF_INET,SOCK_PACKET)\n", 118689bddce5SStephen Hemminger current->comm); 11871da177e4SLinus Torvalds } 11881da177e4SLinus Torvalds family = PF_PACKET; 11891da177e4SLinus Torvalds } 11901da177e4SLinus Torvalds 11911da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, kern); 11921da177e4SLinus Torvalds if (err) 11931da177e4SLinus Torvalds return err; 11941da177e4SLinus Torvalds 119555737fdaSStephen Hemminger /* 119655737fdaSStephen Hemminger * Allocate the socket and allow the family to set things up. if 119755737fdaSStephen Hemminger * the protocol is 0, the family is instructed to select an appropriate 119855737fdaSStephen Hemminger * default. 119955737fdaSStephen Hemminger */ 120055737fdaSStephen Hemminger sock = sock_alloc(); 120155737fdaSStephen Hemminger if (!sock) { 1202e87cc472SJoe Perches net_warn_ratelimited("socket: no more sockets\n"); 120355737fdaSStephen Hemminger return -ENFILE; /* Not exactly a match, but its the 120455737fdaSStephen Hemminger closest posix thing */ 120555737fdaSStephen Hemminger } 120655737fdaSStephen Hemminger 120755737fdaSStephen Hemminger sock->type = type; 120855737fdaSStephen Hemminger 120995a5afcaSJohannes Berg #ifdef CONFIG_MODULES 12101da177e4SLinus Torvalds /* Attempt to load a protocol module if the find failed. 12111da177e4SLinus Torvalds * 12121da177e4SLinus Torvalds * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user 12131da177e4SLinus Torvalds * requested real, full-featured networking support upon configuration. 12141da177e4SLinus Torvalds * Otherwise module support will break! 12151da177e4SLinus Torvalds */ 1216190683a9SEric Dumazet if (rcu_access_pointer(net_families[family]) == NULL) 12171da177e4SLinus Torvalds request_module("net-pf-%d", family); 12181da177e4SLinus Torvalds #endif 12191da177e4SLinus Torvalds 122055737fdaSStephen Hemminger rcu_read_lock(); 122155737fdaSStephen Hemminger pf = rcu_dereference(net_families[family]); 12221da177e4SLinus Torvalds err = -EAFNOSUPPORT; 122355737fdaSStephen Hemminger if (!pf) 122455737fdaSStephen Hemminger goto out_release; 12251da177e4SLinus Torvalds 12261da177e4SLinus Torvalds /* 12271da177e4SLinus Torvalds * We will call the ->create function, that possibly is in a loadable 12281da177e4SLinus Torvalds * module, so we have to bump that loadable module refcnt first. 12291da177e4SLinus Torvalds */ 123055737fdaSStephen Hemminger if (!try_module_get(pf->owner)) 12311da177e4SLinus Torvalds goto out_release; 12321da177e4SLinus Torvalds 123355737fdaSStephen Hemminger /* Now protected by module ref count */ 123455737fdaSStephen Hemminger rcu_read_unlock(); 123555737fdaSStephen Hemminger 12363f378b68SEric Paris err = pf->create(net, sock, protocol, kern); 123755737fdaSStephen Hemminger if (err < 0) 12381da177e4SLinus Torvalds goto out_module_put; 1239a79af59eSFrank Filz 12401da177e4SLinus Torvalds /* 12411da177e4SLinus Torvalds * Now to bump the refcnt of the [loadable] module that owns this 12421da177e4SLinus Torvalds * socket at sock_release time we decrement its refcnt. 12431da177e4SLinus Torvalds */ 124455737fdaSStephen Hemminger if (!try_module_get(sock->ops->owner)) 124555737fdaSStephen Hemminger goto out_module_busy; 124655737fdaSStephen Hemminger 12471da177e4SLinus Torvalds /* 12481da177e4SLinus Torvalds * Now that we're done with the ->create function, the [loadable] 12491da177e4SLinus Torvalds * module can have its refcnt decremented 12501da177e4SLinus Torvalds */ 125155737fdaSStephen Hemminger module_put(pf->owner); 12527420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, kern); 12537420ed23SVenkat Yekkirala if (err) 12543b185525SHerbert Xu goto out_sock_release; 125555737fdaSStephen Hemminger *res = sock; 12561da177e4SLinus Torvalds 125755737fdaSStephen Hemminger return 0; 125855737fdaSStephen Hemminger 125955737fdaSStephen Hemminger out_module_busy: 126055737fdaSStephen Hemminger err = -EAFNOSUPPORT; 12611da177e4SLinus Torvalds out_module_put: 126255737fdaSStephen Hemminger sock->ops = NULL; 126355737fdaSStephen Hemminger module_put(pf->owner); 126455737fdaSStephen Hemminger out_sock_release: 12651da177e4SLinus Torvalds sock_release(sock); 126655737fdaSStephen Hemminger return err; 126755737fdaSStephen Hemminger 126855737fdaSStephen Hemminger out_release: 126955737fdaSStephen Hemminger rcu_read_unlock(); 127055737fdaSStephen Hemminger goto out_sock_release; 12711da177e4SLinus Torvalds } 1272721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create); 12731da177e4SLinus Torvalds 12741da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res) 12751da177e4SLinus Torvalds { 12761b8d7ae4SEric W. Biederman return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); 12771da177e4SLinus Torvalds } 1278c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create); 12791da177e4SLinus Torvalds 12801da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res) 12811da177e4SLinus Torvalds { 12821b8d7ae4SEric W. Biederman return __sock_create(&init_net, family, type, protocol, res, 1); 12831da177e4SLinus Torvalds } 1284c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern); 12851da177e4SLinus Torvalds 12863e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) 12871da177e4SLinus Torvalds { 12881da177e4SLinus Torvalds int retval; 12891da177e4SLinus Torvalds struct socket *sock; 1290a677a039SUlrich Drepper int flags; 1291a677a039SUlrich Drepper 1292e38b36f3SUlrich Drepper /* Check the SOCK_* constants for consistency. */ 1293e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); 1294e38b36f3SUlrich Drepper BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); 1295e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); 1296e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); 1297e38b36f3SUlrich Drepper 1298a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 129977d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1300a677a039SUlrich Drepper return -EINVAL; 1301a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13021da177e4SLinus Torvalds 1303aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1304aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1305aaca0bdcSUlrich Drepper 13061da177e4SLinus Torvalds retval = sock_create(family, type, protocol, &sock); 13071da177e4SLinus Torvalds if (retval < 0) 13081da177e4SLinus Torvalds goto out; 13091da177e4SLinus Torvalds 131077d27200SUlrich Drepper retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); 13111da177e4SLinus Torvalds if (retval < 0) 13121da177e4SLinus Torvalds goto out_release; 13131da177e4SLinus Torvalds 13141da177e4SLinus Torvalds out: 13151da177e4SLinus Torvalds /* It may be already another descriptor 8) Not kernel problem. */ 13161da177e4SLinus Torvalds return retval; 13171da177e4SLinus Torvalds 13181da177e4SLinus Torvalds out_release: 13191da177e4SLinus Torvalds sock_release(sock); 13201da177e4SLinus Torvalds return retval; 13211da177e4SLinus Torvalds } 13221da177e4SLinus Torvalds 13231da177e4SLinus Torvalds /* 13241da177e4SLinus Torvalds * Create a pair of connected sockets. 13251da177e4SLinus Torvalds */ 13261da177e4SLinus Torvalds 13273e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, 13283e0fa65fSHeiko Carstens int __user *, usockvec) 13291da177e4SLinus Torvalds { 13301da177e4SLinus Torvalds struct socket *sock1, *sock2; 13311da177e4SLinus Torvalds int fd1, fd2, err; 1332db349509SAl Viro struct file *newfile1, *newfile2; 1333a677a039SUlrich Drepper int flags; 1334a677a039SUlrich Drepper 1335a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 133677d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1337a677a039SUlrich Drepper return -EINVAL; 1338a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 13391da177e4SLinus Torvalds 1340aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1341aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1342aaca0bdcSUlrich Drepper 13431da177e4SLinus Torvalds /* 13441da177e4SLinus Torvalds * Obtain the first socket and check if the underlying protocol 13451da177e4SLinus Torvalds * supports the socketpair call. 13461da177e4SLinus Torvalds */ 13471da177e4SLinus Torvalds 13481da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock1); 13491da177e4SLinus Torvalds if (err < 0) 13501da177e4SLinus Torvalds goto out; 13511da177e4SLinus Torvalds 13521da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock2); 13531da177e4SLinus Torvalds if (err < 0) 13541da177e4SLinus Torvalds goto out_release_1; 13551da177e4SLinus Torvalds 13561da177e4SLinus Torvalds err = sock1->ops->socketpair(sock1, sock2); 13571da177e4SLinus Torvalds if (err < 0) 13581da177e4SLinus Torvalds goto out_release_both; 13591da177e4SLinus Torvalds 136028407630SAl Viro fd1 = get_unused_fd_flags(flags); 1361bf3c23d1SDavid S. Miller if (unlikely(fd1 < 0)) { 1362bf3c23d1SDavid S. Miller err = fd1; 13631da177e4SLinus Torvalds goto out_release_both; 1364bf3c23d1SDavid S. Miller } 1365d73aa286SYann Droneaud 136628407630SAl Viro fd2 = get_unused_fd_flags(flags); 1367198de4d7SAl Viro if (unlikely(fd2 < 0)) { 1368198de4d7SAl Viro err = fd2; 1369d73aa286SYann Droneaud goto out_put_unused_1; 137028407630SAl Viro } 137128407630SAl Viro 1372aab174f0SLinus Torvalds newfile1 = sock_alloc_file(sock1, flags, NULL); 137328407630SAl Viro if (unlikely(IS_ERR(newfile1))) { 137428407630SAl Viro err = PTR_ERR(newfile1); 1375d73aa286SYann Droneaud goto out_put_unused_both; 137628407630SAl Viro } 137728407630SAl Viro 1378aab174f0SLinus Torvalds newfile2 = sock_alloc_file(sock2, flags, NULL); 137928407630SAl Viro if (IS_ERR(newfile2)) { 138028407630SAl Viro err = PTR_ERR(newfile2); 1381d73aa286SYann Droneaud goto out_fput_1; 1382db349509SAl Viro } 1383db349509SAl Viro 1384d73aa286SYann Droneaud err = put_user(fd1, &usockvec[0]); 1385d73aa286SYann Droneaud if (err) 1386d73aa286SYann Droneaud goto out_fput_both; 1387d73aa286SYann Droneaud 1388d73aa286SYann Droneaud err = put_user(fd2, &usockvec[1]); 1389d73aa286SYann Droneaud if (err) 1390d73aa286SYann Droneaud goto out_fput_both; 1391d73aa286SYann Droneaud 1392157cf649SAl Viro audit_fd_pair(fd1, fd2); 1393d73aa286SYann Droneaud 1394db349509SAl Viro fd_install(fd1, newfile1); 1395db349509SAl Viro fd_install(fd2, newfile2); 13961da177e4SLinus Torvalds /* fd1 and fd2 may be already another descriptors. 13971da177e4SLinus Torvalds * Not kernel problem. 13981da177e4SLinus Torvalds */ 13991da177e4SLinus Torvalds 14001da177e4SLinus Torvalds return 0; 14011da177e4SLinus Torvalds 1402d73aa286SYann Droneaud out_fput_both: 1403d73aa286SYann Droneaud fput(newfile2); 1404d73aa286SYann Droneaud fput(newfile1); 1405d73aa286SYann Droneaud put_unused_fd(fd2); 1406d73aa286SYann Droneaud put_unused_fd(fd1); 1407d73aa286SYann Droneaud goto out; 14081da177e4SLinus Torvalds 1409d73aa286SYann Droneaud out_fput_1: 1410d73aa286SYann Droneaud fput(newfile1); 1411d73aa286SYann Droneaud put_unused_fd(fd2); 1412d73aa286SYann Droneaud put_unused_fd(fd1); 1413d73aa286SYann Droneaud sock_release(sock2); 1414d73aa286SYann Droneaud goto out; 1415d73aa286SYann Droneaud 1416d73aa286SYann Droneaud out_put_unused_both: 1417d73aa286SYann Droneaud put_unused_fd(fd2); 1418d73aa286SYann Droneaud out_put_unused_1: 1419d73aa286SYann Droneaud put_unused_fd(fd1); 14201da177e4SLinus Torvalds out_release_both: 14211da177e4SLinus Torvalds sock_release(sock2); 14221da177e4SLinus Torvalds out_release_1: 14231da177e4SLinus Torvalds sock_release(sock1); 14241da177e4SLinus Torvalds out: 14251da177e4SLinus Torvalds return err; 14261da177e4SLinus Torvalds } 14271da177e4SLinus Torvalds 14281da177e4SLinus Torvalds /* 14291da177e4SLinus Torvalds * Bind a name to a socket. Nothing much to do here since it's 14301da177e4SLinus Torvalds * the protocol's responsibility to handle the local address. 14311da177e4SLinus Torvalds * 14321da177e4SLinus Torvalds * We move the socket address to kernel space before we call 14331da177e4SLinus Torvalds * the protocol layer (having also checked the address is ok). 14341da177e4SLinus Torvalds */ 14351da177e4SLinus Torvalds 143620f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) 14371da177e4SLinus Torvalds { 14381da177e4SLinus Torvalds struct socket *sock; 1439230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 14406cb153caSBenjamin LaHaise int err, fput_needed; 14411da177e4SLinus Torvalds 144289bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 144389bddce5SStephen Hemminger if (sock) { 144443db362dSMaciej Żenczykowski err = move_addr_to_kernel(umyaddr, addrlen, &address); 144589bddce5SStephen Hemminger if (err >= 0) { 144689bddce5SStephen Hemminger err = security_socket_bind(sock, 1447230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 144889bddce5SStephen Hemminger addrlen); 14496cb153caSBenjamin LaHaise if (!err) 14506cb153caSBenjamin LaHaise err = sock->ops->bind(sock, 145189bddce5SStephen Hemminger (struct sockaddr *) 1452230b1839SYOSHIFUJI Hideaki &address, addrlen); 14531da177e4SLinus Torvalds } 14546cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 14551da177e4SLinus Torvalds } 14561da177e4SLinus Torvalds return err; 14571da177e4SLinus Torvalds } 14581da177e4SLinus Torvalds 14591da177e4SLinus Torvalds /* 14601da177e4SLinus Torvalds * Perform a listen. Basically, we allow the protocol to do anything 14611da177e4SLinus Torvalds * necessary for a listen, and if that works, we mark the socket as 14621da177e4SLinus Torvalds * ready for listening. 14631da177e4SLinus Torvalds */ 14641da177e4SLinus Torvalds 14653e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog) 14661da177e4SLinus Torvalds { 14671da177e4SLinus Torvalds struct socket *sock; 14686cb153caSBenjamin LaHaise int err, fput_needed; 1469b8e1f9b5SPavel Emelyanov int somaxconn; 14701da177e4SLinus Torvalds 147189bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 147289bddce5SStephen Hemminger if (sock) { 14738efa6e93SPavel Emelyanov somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 147495c96174SEric Dumazet if ((unsigned int)backlog > somaxconn) 1475b8e1f9b5SPavel Emelyanov backlog = somaxconn; 14761da177e4SLinus Torvalds 14771da177e4SLinus Torvalds err = security_socket_listen(sock, backlog); 14786cb153caSBenjamin LaHaise if (!err) 14791da177e4SLinus Torvalds err = sock->ops->listen(sock, backlog); 14806cb153caSBenjamin LaHaise 14816cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 14821da177e4SLinus Torvalds } 14831da177e4SLinus Torvalds return err; 14841da177e4SLinus Torvalds } 14851da177e4SLinus Torvalds 14861da177e4SLinus Torvalds /* 14871da177e4SLinus Torvalds * For accept, we attempt to create a new socket, set up the link 14881da177e4SLinus Torvalds * with the client, wake up the client, then return the new 14891da177e4SLinus Torvalds * connected fd. We collect the address of the connector in kernel 14901da177e4SLinus Torvalds * space and move it to user at the very end. This is unclean because 14911da177e4SLinus Torvalds * we open the socket then return an error. 14921da177e4SLinus Torvalds * 14931da177e4SLinus Torvalds * 1003.1g adds the ability to recvmsg() to query connection pending 14941da177e4SLinus Torvalds * status to recvmsg. We need to add that support in a way thats 14951da177e4SLinus Torvalds * clean when we restucture accept also. 14961da177e4SLinus Torvalds */ 14971da177e4SLinus Torvalds 149820f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, 149920f37034SHeiko Carstens int __user *, upeer_addrlen, int, flags) 15001da177e4SLinus Torvalds { 15011da177e4SLinus Torvalds struct socket *sock, *newsock; 150239d8c1b6SDavid S. Miller struct file *newfile; 15036cb153caSBenjamin LaHaise int err, len, newfd, fput_needed; 1504230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 15051da177e4SLinus Torvalds 150677d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1507aaca0bdcSUlrich Drepper return -EINVAL; 1508aaca0bdcSUlrich Drepper 1509aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1510aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1511aaca0bdcSUlrich Drepper 15126cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 15131da177e4SLinus Torvalds if (!sock) 15141da177e4SLinus Torvalds goto out; 15151da177e4SLinus Torvalds 15161da177e4SLinus Torvalds err = -ENFILE; 1517c6d409cfSEric Dumazet newsock = sock_alloc(); 1518c6d409cfSEric Dumazet if (!newsock) 15191da177e4SLinus Torvalds goto out_put; 15201da177e4SLinus Torvalds 15211da177e4SLinus Torvalds newsock->type = sock->type; 15221da177e4SLinus Torvalds newsock->ops = sock->ops; 15231da177e4SLinus Torvalds 15241da177e4SLinus Torvalds /* 15251da177e4SLinus Torvalds * We don't need try_module_get here, as the listening socket (sock) 15261da177e4SLinus Torvalds * has the protocol module (sock->ops->owner) held. 15271da177e4SLinus Torvalds */ 15281da177e4SLinus Torvalds __module_get(newsock->ops->owner); 15291da177e4SLinus Torvalds 153028407630SAl Viro newfd = get_unused_fd_flags(flags); 153139d8c1b6SDavid S. Miller if (unlikely(newfd < 0)) { 153239d8c1b6SDavid S. Miller err = newfd; 15339a1875e6SDavid S. Miller sock_release(newsock); 15349a1875e6SDavid S. Miller goto out_put; 153539d8c1b6SDavid S. Miller } 1536aab174f0SLinus Torvalds newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); 153728407630SAl Viro if (unlikely(IS_ERR(newfile))) { 153828407630SAl Viro err = PTR_ERR(newfile); 153928407630SAl Viro put_unused_fd(newfd); 154028407630SAl Viro sock_release(newsock); 154128407630SAl Viro goto out_put; 154228407630SAl Viro } 154339d8c1b6SDavid S. Miller 1544a79af59eSFrank Filz err = security_socket_accept(sock, newsock); 1545a79af59eSFrank Filz if (err) 154639d8c1b6SDavid S. Miller goto out_fd; 1547a79af59eSFrank Filz 15481da177e4SLinus Torvalds err = sock->ops->accept(sock, newsock, sock->file->f_flags); 15491da177e4SLinus Torvalds if (err < 0) 155039d8c1b6SDavid S. Miller goto out_fd; 15511da177e4SLinus Torvalds 15521da177e4SLinus Torvalds if (upeer_sockaddr) { 1553230b1839SYOSHIFUJI Hideaki if (newsock->ops->getname(newsock, (struct sockaddr *)&address, 155489bddce5SStephen Hemminger &len, 2) < 0) { 15551da177e4SLinus Torvalds err = -ECONNABORTED; 155639d8c1b6SDavid S. Miller goto out_fd; 15571da177e4SLinus Torvalds } 155843db362dSMaciej Żenczykowski err = move_addr_to_user(&address, 1559230b1839SYOSHIFUJI Hideaki len, upeer_sockaddr, upeer_addrlen); 15601da177e4SLinus Torvalds if (err < 0) 156139d8c1b6SDavid S. Miller goto out_fd; 15621da177e4SLinus Torvalds } 15631da177e4SLinus Torvalds 15641da177e4SLinus Torvalds /* File flags are not inherited via accept() unlike another OSes. */ 15651da177e4SLinus Torvalds 156639d8c1b6SDavid S. Miller fd_install(newfd, newfile); 156739d8c1b6SDavid S. Miller err = newfd; 15681da177e4SLinus Torvalds 15691da177e4SLinus Torvalds out_put: 15706cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 15711da177e4SLinus Torvalds out: 15721da177e4SLinus Torvalds return err; 157339d8c1b6SDavid S. Miller out_fd: 15749606a216SDavid S. Miller fput(newfile); 157539d8c1b6SDavid S. Miller put_unused_fd(newfd); 15761da177e4SLinus Torvalds goto out_put; 15771da177e4SLinus Torvalds } 15781da177e4SLinus Torvalds 157920f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, 158020f37034SHeiko Carstens int __user *, upeer_addrlen) 1581aaca0bdcSUlrich Drepper { 1582de11defeSUlrich Drepper return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); 1583aaca0bdcSUlrich Drepper } 1584aaca0bdcSUlrich Drepper 15851da177e4SLinus Torvalds /* 15861da177e4SLinus Torvalds * Attempt to connect to a socket with the server address. The address 15871da177e4SLinus Torvalds * is in user space so we verify it is OK and move it to kernel space. 15881da177e4SLinus Torvalds * 15891da177e4SLinus Torvalds * For 1003.1g we need to add clean support for a bind to AF_UNSPEC to 15901da177e4SLinus Torvalds * break bindings 15911da177e4SLinus Torvalds * 15921da177e4SLinus Torvalds * NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and 15931da177e4SLinus Torvalds * other SEQPACKET protocols that take time to connect() as it doesn't 15941da177e4SLinus Torvalds * include the -EINPROGRESS status for such sockets. 15951da177e4SLinus Torvalds */ 15961da177e4SLinus Torvalds 159720f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, 159820f37034SHeiko Carstens int, addrlen) 15991da177e4SLinus Torvalds { 16001da177e4SLinus Torvalds struct socket *sock; 1601230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16026cb153caSBenjamin LaHaise int err, fput_needed; 16031da177e4SLinus Torvalds 16046cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16051da177e4SLinus Torvalds if (!sock) 16061da177e4SLinus Torvalds goto out; 160743db362dSMaciej Żenczykowski err = move_addr_to_kernel(uservaddr, addrlen, &address); 16081da177e4SLinus Torvalds if (err < 0) 16091da177e4SLinus Torvalds goto out_put; 16101da177e4SLinus Torvalds 161189bddce5SStephen Hemminger err = 1612230b1839SYOSHIFUJI Hideaki security_socket_connect(sock, (struct sockaddr *)&address, addrlen); 16131da177e4SLinus Torvalds if (err) 16141da177e4SLinus Torvalds goto out_put; 16151da177e4SLinus Torvalds 1616230b1839SYOSHIFUJI Hideaki err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, 16171da177e4SLinus Torvalds sock->file->f_flags); 16181da177e4SLinus Torvalds out_put: 16196cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16201da177e4SLinus Torvalds out: 16211da177e4SLinus Torvalds return err; 16221da177e4SLinus Torvalds } 16231da177e4SLinus Torvalds 16241da177e4SLinus Torvalds /* 16251da177e4SLinus Torvalds * Get the local address ('name') of a socket object. Move the obtained 16261da177e4SLinus Torvalds * name to user space. 16271da177e4SLinus Torvalds */ 16281da177e4SLinus Torvalds 162920f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr, 163020f37034SHeiko Carstens int __user *, usockaddr_len) 16311da177e4SLinus Torvalds { 16321da177e4SLinus Torvalds struct socket *sock; 1633230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16346cb153caSBenjamin LaHaise int len, err, fput_needed; 16351da177e4SLinus Torvalds 16366cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 16371da177e4SLinus Torvalds if (!sock) 16381da177e4SLinus Torvalds goto out; 16391da177e4SLinus Torvalds 16401da177e4SLinus Torvalds err = security_socket_getsockname(sock); 16411da177e4SLinus Torvalds if (err) 16421da177e4SLinus Torvalds goto out_put; 16431da177e4SLinus Torvalds 1644230b1839SYOSHIFUJI Hideaki err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0); 16451da177e4SLinus Torvalds if (err) 16461da177e4SLinus Torvalds goto out_put; 164743db362dSMaciej Żenczykowski err = move_addr_to_user(&address, len, usockaddr, usockaddr_len); 16481da177e4SLinus Torvalds 16491da177e4SLinus Torvalds out_put: 16506cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16511da177e4SLinus Torvalds out: 16521da177e4SLinus Torvalds return err; 16531da177e4SLinus Torvalds } 16541da177e4SLinus Torvalds 16551da177e4SLinus Torvalds /* 16561da177e4SLinus Torvalds * Get the remote address ('name') of a socket object. Move the obtained 16571da177e4SLinus Torvalds * name to user space. 16581da177e4SLinus Torvalds */ 16591da177e4SLinus Torvalds 166020f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, 166120f37034SHeiko Carstens int __user *, usockaddr_len) 16621da177e4SLinus Torvalds { 16631da177e4SLinus Torvalds struct socket *sock; 1664230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16656cb153caSBenjamin LaHaise int len, err, fput_needed; 16661da177e4SLinus Torvalds 166789bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 166889bddce5SStephen Hemminger if (sock != NULL) { 16691da177e4SLinus Torvalds err = security_socket_getpeername(sock); 16701da177e4SLinus Torvalds if (err) { 16716cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16721da177e4SLinus Torvalds return err; 16731da177e4SLinus Torvalds } 16741da177e4SLinus Torvalds 167589bddce5SStephen Hemminger err = 1676230b1839SYOSHIFUJI Hideaki sock->ops->getname(sock, (struct sockaddr *)&address, &len, 167789bddce5SStephen Hemminger 1); 16781da177e4SLinus Torvalds if (!err) 167943db362dSMaciej Żenczykowski err = move_addr_to_user(&address, len, usockaddr, 168089bddce5SStephen Hemminger usockaddr_len); 16816cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16821da177e4SLinus Torvalds } 16831da177e4SLinus Torvalds return err; 16841da177e4SLinus Torvalds } 16851da177e4SLinus Torvalds 16861da177e4SLinus Torvalds /* 16871da177e4SLinus Torvalds * Send a datagram to a given address. We move the address into kernel 16881da177e4SLinus Torvalds * space and check the user space data area is readable before invoking 16891da177e4SLinus Torvalds * the protocol. 16901da177e4SLinus Torvalds */ 16911da177e4SLinus Torvalds 16923e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, 169395c96174SEric Dumazet unsigned int, flags, struct sockaddr __user *, addr, 16943e0fa65fSHeiko Carstens int, addr_len) 16951da177e4SLinus Torvalds { 16961da177e4SLinus Torvalds struct socket *sock; 1697230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16981da177e4SLinus Torvalds int err; 16991da177e4SLinus Torvalds struct msghdr msg; 17001da177e4SLinus Torvalds struct iovec iov; 17016cb153caSBenjamin LaHaise int fput_needed; 17021da177e4SLinus Torvalds 1703253eacc0SLinus Torvalds if (len > INT_MAX) 1704253eacc0SLinus Torvalds len = INT_MAX; 1705de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 1706de0fa95cSPavel Emelyanov if (!sock) 17074387ff75SDavid S. Miller goto out; 17086cb153caSBenjamin LaHaise 17091da177e4SLinus Torvalds iov.iov_base = buff; 17101da177e4SLinus Torvalds iov.iov_len = len; 17111da177e4SLinus Torvalds msg.msg_name = NULL; 1712c0371da6SAl Viro iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, len); 17131da177e4SLinus Torvalds msg.msg_control = NULL; 17141da177e4SLinus Torvalds msg.msg_controllen = 0; 17151da177e4SLinus Torvalds msg.msg_namelen = 0; 17166cb153caSBenjamin LaHaise if (addr) { 171743db362dSMaciej Żenczykowski err = move_addr_to_kernel(addr, addr_len, &address); 17181da177e4SLinus Torvalds if (err < 0) 17191da177e4SLinus Torvalds goto out_put; 1720230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 17211da177e4SLinus Torvalds msg.msg_namelen = addr_len; 17221da177e4SLinus Torvalds } 17231da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 17241da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 17251da177e4SLinus Torvalds msg.msg_flags = flags; 17261da177e4SLinus Torvalds err = sock_sendmsg(sock, &msg, len); 17271da177e4SLinus Torvalds 17281da177e4SLinus Torvalds out_put: 1729de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 17304387ff75SDavid S. Miller out: 17311da177e4SLinus Torvalds return err; 17321da177e4SLinus Torvalds } 17331da177e4SLinus Torvalds 17341da177e4SLinus Torvalds /* 17351da177e4SLinus Torvalds * Send a datagram down a socket. 17361da177e4SLinus Torvalds */ 17371da177e4SLinus Torvalds 17383e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, 173995c96174SEric Dumazet unsigned int, flags) 17401da177e4SLinus Torvalds { 17411da177e4SLinus Torvalds return sys_sendto(fd, buff, len, flags, NULL, 0); 17421da177e4SLinus Torvalds } 17431da177e4SLinus Torvalds 17441da177e4SLinus Torvalds /* 17451da177e4SLinus Torvalds * Receive a frame from the socket and optionally record the address of the 17461da177e4SLinus Torvalds * sender. We verify the buffers are writable and if needed move the 17471da177e4SLinus Torvalds * sender address from kernel to user space. 17481da177e4SLinus Torvalds */ 17491da177e4SLinus Torvalds 17503e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, 175195c96174SEric Dumazet unsigned int, flags, struct sockaddr __user *, addr, 17523e0fa65fSHeiko Carstens int __user *, addr_len) 17531da177e4SLinus Torvalds { 17541da177e4SLinus Torvalds struct socket *sock; 17551da177e4SLinus Torvalds struct iovec iov; 17561da177e4SLinus Torvalds struct msghdr msg; 1757230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17581da177e4SLinus Torvalds int err, err2; 17596cb153caSBenjamin LaHaise int fput_needed; 17601da177e4SLinus Torvalds 1761253eacc0SLinus Torvalds if (size > INT_MAX) 1762253eacc0SLinus Torvalds size = INT_MAX; 1763de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 17641da177e4SLinus Torvalds if (!sock) 1765de0fa95cSPavel Emelyanov goto out; 17661da177e4SLinus Torvalds 17671da177e4SLinus Torvalds msg.msg_control = NULL; 17681da177e4SLinus Torvalds msg.msg_controllen = 0; 17691da177e4SLinus Torvalds iov.iov_len = size; 17701da177e4SLinus Torvalds iov.iov_base = ubuf; 1771c0371da6SAl Viro iov_iter_init(&msg.msg_iter, READ, &iov, 1, size); 1772f3d33426SHannes Frederic Sowa /* Save some cycles and don't copy the address if not needed */ 1773f3d33426SHannes Frederic Sowa msg.msg_name = addr ? (struct sockaddr *)&address : NULL; 1774f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 1775f3d33426SHannes Frederic Sowa msg.msg_namelen = 0; 17761da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 17771da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 17781da177e4SLinus Torvalds err = sock_recvmsg(sock, &msg, size, flags); 17791da177e4SLinus Torvalds 178089bddce5SStephen Hemminger if (err >= 0 && addr != NULL) { 178143db362dSMaciej Żenczykowski err2 = move_addr_to_user(&address, 1782230b1839SYOSHIFUJI Hideaki msg.msg_namelen, addr, addr_len); 17831da177e4SLinus Torvalds if (err2 < 0) 17841da177e4SLinus Torvalds err = err2; 17851da177e4SLinus Torvalds } 1786de0fa95cSPavel Emelyanov 1787de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 17884387ff75SDavid S. Miller out: 17891da177e4SLinus Torvalds return err; 17901da177e4SLinus Torvalds } 17911da177e4SLinus Torvalds 17921da177e4SLinus Torvalds /* 17931da177e4SLinus Torvalds * Receive a datagram from a socket. 17941da177e4SLinus Torvalds */ 17951da177e4SLinus Torvalds 1796b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size, 1797b7c0ddf5SJan Glauber unsigned int, flags) 17981da177e4SLinus Torvalds { 17991da177e4SLinus Torvalds return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); 18001da177e4SLinus Torvalds } 18011da177e4SLinus Torvalds 18021da177e4SLinus Torvalds /* 18031da177e4SLinus Torvalds * Set a socket option. Because we don't know the option lengths we have 18041da177e4SLinus Torvalds * to pass the user mode parameter for the protocols to sort out. 18051da177e4SLinus Torvalds */ 18061da177e4SLinus Torvalds 180720f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, 180820f37034SHeiko Carstens char __user *, optval, int, optlen) 18091da177e4SLinus Torvalds { 18106cb153caSBenjamin LaHaise int err, fput_needed; 18111da177e4SLinus Torvalds struct socket *sock; 18121da177e4SLinus Torvalds 18131da177e4SLinus Torvalds if (optlen < 0) 18141da177e4SLinus Torvalds return -EINVAL; 18151da177e4SLinus Torvalds 181689bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 181789bddce5SStephen Hemminger if (sock != NULL) { 18181da177e4SLinus Torvalds err = security_socket_setsockopt(sock, level, optname); 18196cb153caSBenjamin LaHaise if (err) 18206cb153caSBenjamin LaHaise goto out_put; 18211da177e4SLinus Torvalds 18221da177e4SLinus Torvalds if (level == SOL_SOCKET) 182389bddce5SStephen Hemminger err = 182489bddce5SStephen Hemminger sock_setsockopt(sock, level, optname, optval, 182589bddce5SStephen Hemminger optlen); 18261da177e4SLinus Torvalds else 182789bddce5SStephen Hemminger err = 182889bddce5SStephen Hemminger sock->ops->setsockopt(sock, level, optname, optval, 182989bddce5SStephen Hemminger optlen); 18306cb153caSBenjamin LaHaise out_put: 18316cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18321da177e4SLinus Torvalds } 18331da177e4SLinus Torvalds return err; 18341da177e4SLinus Torvalds } 18351da177e4SLinus Torvalds 18361da177e4SLinus Torvalds /* 18371da177e4SLinus Torvalds * Get a socket option. Because we don't know the option lengths we have 18381da177e4SLinus Torvalds * to pass a user mode parameter for the protocols to sort out. 18391da177e4SLinus Torvalds */ 18401da177e4SLinus Torvalds 184120f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, 184220f37034SHeiko Carstens char __user *, optval, int __user *, optlen) 18431da177e4SLinus Torvalds { 18446cb153caSBenjamin LaHaise int err, fput_needed; 18451da177e4SLinus Torvalds struct socket *sock; 18461da177e4SLinus Torvalds 184789bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 184889bddce5SStephen Hemminger if (sock != NULL) { 18496cb153caSBenjamin LaHaise err = security_socket_getsockopt(sock, level, optname); 18506cb153caSBenjamin LaHaise if (err) 18516cb153caSBenjamin LaHaise goto out_put; 18521da177e4SLinus Torvalds 18531da177e4SLinus Torvalds if (level == SOL_SOCKET) 185489bddce5SStephen Hemminger err = 185589bddce5SStephen Hemminger sock_getsockopt(sock, level, optname, optval, 185689bddce5SStephen Hemminger optlen); 18571da177e4SLinus Torvalds else 185889bddce5SStephen Hemminger err = 185989bddce5SStephen Hemminger sock->ops->getsockopt(sock, level, optname, optval, 186089bddce5SStephen Hemminger optlen); 18616cb153caSBenjamin LaHaise out_put: 18626cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18631da177e4SLinus Torvalds } 18641da177e4SLinus Torvalds return err; 18651da177e4SLinus Torvalds } 18661da177e4SLinus Torvalds 18671da177e4SLinus Torvalds /* 18681da177e4SLinus Torvalds * Shutdown a socket. 18691da177e4SLinus Torvalds */ 18701da177e4SLinus Torvalds 1871754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how) 18721da177e4SLinus Torvalds { 18736cb153caSBenjamin LaHaise int err, fput_needed; 18741da177e4SLinus Torvalds struct socket *sock; 18751da177e4SLinus Torvalds 187689bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 187789bddce5SStephen Hemminger if (sock != NULL) { 18781da177e4SLinus Torvalds err = security_socket_shutdown(sock, how); 18796cb153caSBenjamin LaHaise if (!err) 18801da177e4SLinus Torvalds err = sock->ops->shutdown(sock, how); 18816cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 18821da177e4SLinus Torvalds } 18831da177e4SLinus Torvalds return err; 18841da177e4SLinus Torvalds } 18851da177e4SLinus Torvalds 18861da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit 18871da177e4SLinus Torvalds * fields which are the same type (int / unsigned) on our platforms. 18881da177e4SLinus Torvalds */ 18891da177e4SLinus Torvalds #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) 18901da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) 18911da177e4SLinus Torvalds #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) 18921da177e4SLinus Torvalds 1893c71d8ebeSTetsuo Handa struct used_address { 1894c71d8ebeSTetsuo Handa struct sockaddr_storage name; 1895c71d8ebeSTetsuo Handa unsigned int name_len; 1896c71d8ebeSTetsuo Handa }; 1897c71d8ebeSTetsuo Handa 189808adb7daSAl Viro static ssize_t copy_msghdr_from_user(struct msghdr *kmsg, 189908adb7daSAl Viro struct user_msghdr __user *umsg, 190008adb7daSAl Viro struct sockaddr __user **save_addr, 190108adb7daSAl Viro struct iovec **iov) 19021661bf36SDan Carpenter { 190308adb7daSAl Viro struct sockaddr __user *uaddr; 190408adb7daSAl Viro struct iovec __user *uiov; 1905c0371da6SAl Viro size_t nr_segs; 190608adb7daSAl Viro ssize_t err; 190708adb7daSAl Viro 190808adb7daSAl Viro if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || 190908adb7daSAl Viro __get_user(uaddr, &umsg->msg_name) || 191008adb7daSAl Viro __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || 191108adb7daSAl Viro __get_user(uiov, &umsg->msg_iov) || 1912c0371da6SAl Viro __get_user(nr_segs, &umsg->msg_iovlen) || 191308adb7daSAl Viro __get_user(kmsg->msg_control, &umsg->msg_control) || 191408adb7daSAl Viro __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || 191508adb7daSAl Viro __get_user(kmsg->msg_flags, &umsg->msg_flags)) 19161661bf36SDan Carpenter return -EFAULT; 1917dbb490b9SMatthew Leach 191808adb7daSAl Viro if (!uaddr) 19196a2a2b3aSAni Sinha kmsg->msg_namelen = 0; 19206a2a2b3aSAni Sinha 1921dbb490b9SMatthew Leach if (kmsg->msg_namelen < 0) 1922dbb490b9SMatthew Leach return -EINVAL; 1923dbb490b9SMatthew Leach 19241661bf36SDan Carpenter if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 1925db31c55aSDan Carpenter kmsg->msg_namelen = sizeof(struct sockaddr_storage); 192608adb7daSAl Viro 192708adb7daSAl Viro if (save_addr) 192808adb7daSAl Viro *save_addr = uaddr; 192908adb7daSAl Viro 193008adb7daSAl Viro if (uaddr && kmsg->msg_namelen) { 193108adb7daSAl Viro if (!save_addr) { 193208adb7daSAl Viro err = move_addr_to_kernel(uaddr, kmsg->msg_namelen, 193308adb7daSAl Viro kmsg->msg_name); 193408adb7daSAl Viro if (err < 0) 193508adb7daSAl Viro return err; 193608adb7daSAl Viro } 193708adb7daSAl Viro } else { 193808adb7daSAl Viro kmsg->msg_name = NULL; 193908adb7daSAl Viro kmsg->msg_namelen = 0; 194008adb7daSAl Viro } 194108adb7daSAl Viro 1942c0371da6SAl Viro if (nr_segs > UIO_MAXIOV) 194308adb7daSAl Viro return -EMSGSIZE; 194408adb7daSAl Viro 194508adb7daSAl Viro err = rw_copy_check_uvector(save_addr ? READ : WRITE, 1946c0371da6SAl Viro uiov, nr_segs, 194708adb7daSAl Viro UIO_FASTIOV, *iov, iov); 194808adb7daSAl Viro if (err >= 0) 1949c0371da6SAl Viro iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE, 1950c0371da6SAl Viro *iov, nr_segs, err); 195108adb7daSAl Viro return err; 19521661bf36SDan Carpenter } 19531661bf36SDan Carpenter 1954666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, 195595c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, 1956c71d8ebeSTetsuo Handa struct used_address *used_address) 19571da177e4SLinus Torvalds { 195889bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 195989bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 1960230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 19611da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 1962b9d717a7SAlex Williamson unsigned char ctl[sizeof(struct cmsghdr) + 20] 1963b9d717a7SAlex Williamson __attribute__ ((aligned(sizeof(__kernel_size_t)))); 1964b9d717a7SAlex Williamson /* 20 is size of ipv6_pktinfo */ 19651da177e4SLinus Torvalds unsigned char *ctl_buf = ctl; 196608adb7daSAl Viro int ctl_len, total_len; 196708adb7daSAl Viro ssize_t err; 19681da177e4SLinus Torvalds 196908adb7daSAl Viro msg_sys->msg_name = &address; 19701da177e4SLinus Torvalds 197108449320SAl Viro if (MSG_CMSG_COMPAT & flags) 197208adb7daSAl Viro err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov); 197308449320SAl Viro else 197408adb7daSAl Viro err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov); 19751da177e4SLinus Torvalds if (err < 0) 19761da177e4SLinus Torvalds goto out_freeiov; 19771da177e4SLinus Torvalds total_len = err; 19781da177e4SLinus Torvalds 19791da177e4SLinus Torvalds err = -ENOBUFS; 19801da177e4SLinus Torvalds 1981228e548eSAnton Blanchard if (msg_sys->msg_controllen > INT_MAX) 19821da177e4SLinus Torvalds goto out_freeiov; 1983228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 19841da177e4SLinus Torvalds if ((MSG_CMSG_COMPAT & flags) && ctl_len) { 198589bddce5SStephen Hemminger err = 1986228e548eSAnton Blanchard cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, 198789bddce5SStephen Hemminger sizeof(ctl)); 19881da177e4SLinus Torvalds if (err) 19891da177e4SLinus Torvalds goto out_freeiov; 1990228e548eSAnton Blanchard ctl_buf = msg_sys->msg_control; 1991228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 19921da177e4SLinus Torvalds } else if (ctl_len) { 199389bddce5SStephen Hemminger if (ctl_len > sizeof(ctl)) { 19941da177e4SLinus Torvalds ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); 19951da177e4SLinus Torvalds if (ctl_buf == NULL) 19961da177e4SLinus Torvalds goto out_freeiov; 19971da177e4SLinus Torvalds } 19981da177e4SLinus Torvalds err = -EFAULT; 19991da177e4SLinus Torvalds /* 2000228e548eSAnton Blanchard * Careful! Before this, msg_sys->msg_control contains a user pointer. 20011da177e4SLinus Torvalds * Afterwards, it will be a kernel pointer. Thus the compiler-assisted 20021da177e4SLinus Torvalds * checking falls down on this. 20031da177e4SLinus Torvalds */ 2004fb8621bbSNamhyung Kim if (copy_from_user(ctl_buf, 2005228e548eSAnton Blanchard (void __user __force *)msg_sys->msg_control, 200689bddce5SStephen Hemminger ctl_len)) 20071da177e4SLinus Torvalds goto out_freectl; 2008228e548eSAnton Blanchard msg_sys->msg_control = ctl_buf; 20091da177e4SLinus Torvalds } 2010228e548eSAnton Blanchard msg_sys->msg_flags = flags; 20111da177e4SLinus Torvalds 20121da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 2013228e548eSAnton Blanchard msg_sys->msg_flags |= MSG_DONTWAIT; 2014c71d8ebeSTetsuo Handa /* 2015c71d8ebeSTetsuo Handa * If this is sendmmsg() and current destination address is same as 2016c71d8ebeSTetsuo Handa * previously succeeded address, omit asking LSM's decision. 2017c71d8ebeSTetsuo Handa * used_address->name_len is initialized to UINT_MAX so that the first 2018c71d8ebeSTetsuo Handa * destination address never matches. 2019c71d8ebeSTetsuo Handa */ 2020bc909d9dSMathieu Desnoyers if (used_address && msg_sys->msg_name && 2021bc909d9dSMathieu Desnoyers used_address->name_len == msg_sys->msg_namelen && 2022bc909d9dSMathieu Desnoyers !memcmp(&used_address->name, msg_sys->msg_name, 2023c71d8ebeSTetsuo Handa used_address->name_len)) { 2024c71d8ebeSTetsuo Handa err = sock_sendmsg_nosec(sock, msg_sys, total_len); 2025c71d8ebeSTetsuo Handa goto out_freectl; 2026c71d8ebeSTetsuo Handa } 2027c71d8ebeSTetsuo Handa err = sock_sendmsg(sock, msg_sys, total_len); 2028c71d8ebeSTetsuo Handa /* 2029c71d8ebeSTetsuo Handa * If this is sendmmsg() and sending to current destination address was 2030c71d8ebeSTetsuo Handa * successful, remember it. 2031c71d8ebeSTetsuo Handa */ 2032c71d8ebeSTetsuo Handa if (used_address && err >= 0) { 2033c71d8ebeSTetsuo Handa used_address->name_len = msg_sys->msg_namelen; 2034bc909d9dSMathieu Desnoyers if (msg_sys->msg_name) 2035bc909d9dSMathieu Desnoyers memcpy(&used_address->name, msg_sys->msg_name, 2036c71d8ebeSTetsuo Handa used_address->name_len); 2037c71d8ebeSTetsuo Handa } 20381da177e4SLinus Torvalds 20391da177e4SLinus Torvalds out_freectl: 20401da177e4SLinus Torvalds if (ctl_buf != ctl) 20411da177e4SLinus Torvalds sock_kfree_s(sock->sk, ctl_buf, ctl_len); 20421da177e4SLinus Torvalds out_freeiov: 20431da177e4SLinus Torvalds if (iov != iovstack) 2044a74e9106SEric Dumazet kfree(iov); 2045228e548eSAnton Blanchard return err; 2046228e548eSAnton Blanchard } 2047228e548eSAnton Blanchard 2048228e548eSAnton Blanchard /* 2049228e548eSAnton Blanchard * BSD sendmsg interface 2050228e548eSAnton Blanchard */ 2051228e548eSAnton Blanchard 2052666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags) 2053228e548eSAnton Blanchard { 2054228e548eSAnton Blanchard int fput_needed, err; 2055228e548eSAnton Blanchard struct msghdr msg_sys; 20561be374a0SAndy Lutomirski struct socket *sock; 2057228e548eSAnton Blanchard 20581be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2059228e548eSAnton Blanchard if (!sock) 2060228e548eSAnton Blanchard goto out; 2061228e548eSAnton Blanchard 2062a7526eb5SAndy Lutomirski err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL); 2063228e548eSAnton Blanchard 20646cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 20651da177e4SLinus Torvalds out: 20661da177e4SLinus Torvalds return err; 20671da177e4SLinus Torvalds } 20681da177e4SLinus Torvalds 2069666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags) 2070a7526eb5SAndy Lutomirski { 2071a7526eb5SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 2072a7526eb5SAndy Lutomirski return -EINVAL; 2073a7526eb5SAndy Lutomirski return __sys_sendmsg(fd, msg, flags); 2074a7526eb5SAndy Lutomirski } 2075a7526eb5SAndy Lutomirski 2076228e548eSAnton Blanchard /* 2077228e548eSAnton Blanchard * Linux sendmmsg interface 2078228e548eSAnton Blanchard */ 2079228e548eSAnton Blanchard 2080228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2081228e548eSAnton Blanchard unsigned int flags) 2082228e548eSAnton Blanchard { 2083228e548eSAnton Blanchard int fput_needed, err, datagrams; 2084228e548eSAnton Blanchard struct socket *sock; 2085228e548eSAnton Blanchard struct mmsghdr __user *entry; 2086228e548eSAnton Blanchard struct compat_mmsghdr __user *compat_entry; 2087228e548eSAnton Blanchard struct msghdr msg_sys; 2088c71d8ebeSTetsuo Handa struct used_address used_address; 2089228e548eSAnton Blanchard 209098382f41SAnton Blanchard if (vlen > UIO_MAXIOV) 209198382f41SAnton Blanchard vlen = UIO_MAXIOV; 2092228e548eSAnton Blanchard 2093228e548eSAnton Blanchard datagrams = 0; 2094228e548eSAnton Blanchard 2095228e548eSAnton Blanchard sock = sockfd_lookup_light(fd, &err, &fput_needed); 2096228e548eSAnton Blanchard if (!sock) 2097228e548eSAnton Blanchard return err; 2098228e548eSAnton Blanchard 2099c71d8ebeSTetsuo Handa used_address.name_len = UINT_MAX; 2100228e548eSAnton Blanchard entry = mmsg; 2101228e548eSAnton Blanchard compat_entry = (struct compat_mmsghdr __user *)mmsg; 2102728ffb86SAnton Blanchard err = 0; 2103228e548eSAnton Blanchard 2104228e548eSAnton Blanchard while (datagrams < vlen) { 2105228e548eSAnton Blanchard if (MSG_CMSG_COMPAT & flags) { 2106666547ffSAl Viro err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry, 2107c71d8ebeSTetsuo Handa &msg_sys, flags, &used_address); 2108228e548eSAnton Blanchard if (err < 0) 2109228e548eSAnton Blanchard break; 2110228e548eSAnton Blanchard err = __put_user(err, &compat_entry->msg_len); 2111228e548eSAnton Blanchard ++compat_entry; 2112228e548eSAnton Blanchard } else { 2113a7526eb5SAndy Lutomirski err = ___sys_sendmsg(sock, 2114666547ffSAl Viro (struct user_msghdr __user *)entry, 2115c71d8ebeSTetsuo Handa &msg_sys, flags, &used_address); 2116228e548eSAnton Blanchard if (err < 0) 2117228e548eSAnton Blanchard break; 2118228e548eSAnton Blanchard err = put_user(err, &entry->msg_len); 2119228e548eSAnton Blanchard ++entry; 2120228e548eSAnton Blanchard } 2121228e548eSAnton Blanchard 2122228e548eSAnton Blanchard if (err) 2123228e548eSAnton Blanchard break; 2124228e548eSAnton Blanchard ++datagrams; 2125228e548eSAnton Blanchard } 2126228e548eSAnton Blanchard 2127228e548eSAnton Blanchard fput_light(sock->file, fput_needed); 2128228e548eSAnton Blanchard 2129728ffb86SAnton Blanchard /* We only return an error if no datagrams were able to be sent */ 2130728ffb86SAnton Blanchard if (datagrams != 0) 2131228e548eSAnton Blanchard return datagrams; 2132228e548eSAnton Blanchard 2133228e548eSAnton Blanchard return err; 2134228e548eSAnton Blanchard } 2135228e548eSAnton Blanchard 2136228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, 2137228e548eSAnton Blanchard unsigned int, vlen, unsigned int, flags) 2138228e548eSAnton Blanchard { 21391be374a0SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 21401be374a0SAndy Lutomirski return -EINVAL; 2141228e548eSAnton Blanchard return __sys_sendmmsg(fd, mmsg, vlen, flags); 2142228e548eSAnton Blanchard } 2143228e548eSAnton Blanchard 2144666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, 214595c96174SEric Dumazet struct msghdr *msg_sys, unsigned int flags, int nosec) 21461da177e4SLinus Torvalds { 214789bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 214889bddce5SStephen Hemminger (struct compat_msghdr __user *)msg; 21491da177e4SLinus Torvalds struct iovec iovstack[UIO_FASTIOV]; 21501da177e4SLinus Torvalds struct iovec *iov = iovstack; 21511da177e4SLinus Torvalds unsigned long cmsg_ptr; 215208adb7daSAl Viro int total_len, len; 215308adb7daSAl Viro ssize_t err; 21541da177e4SLinus Torvalds 21551da177e4SLinus Torvalds /* kernel mode address */ 2156230b1839SYOSHIFUJI Hideaki struct sockaddr_storage addr; 21571da177e4SLinus Torvalds 21581da177e4SLinus Torvalds /* user mode address pointers */ 21591da177e4SLinus Torvalds struct sockaddr __user *uaddr; 216008adb7daSAl Viro int __user *uaddr_len = COMPAT_NAMELEN(msg); 21611da177e4SLinus Torvalds 216208adb7daSAl Viro msg_sys->msg_name = &addr; 21631da177e4SLinus Torvalds 2164f3d33426SHannes Frederic Sowa if (MSG_CMSG_COMPAT & flags) 216508adb7daSAl Viro err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov); 2166f3d33426SHannes Frederic Sowa else 216708adb7daSAl Viro err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov); 21681da177e4SLinus Torvalds if (err < 0) 21691da177e4SLinus Torvalds goto out_freeiov; 21701da177e4SLinus Torvalds total_len = err; 21711da177e4SLinus Torvalds 2172a2e27255SArnaldo Carvalho de Melo cmsg_ptr = (unsigned long)msg_sys->msg_control; 2173a2e27255SArnaldo Carvalho de Melo msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 21741da177e4SLinus Torvalds 2175f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 2176f3d33426SHannes Frederic Sowa msg_sys->msg_namelen = 0; 2177f3d33426SHannes Frederic Sowa 21781da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 21791da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 2180a2e27255SArnaldo Carvalho de Melo err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, 2181a2e27255SArnaldo Carvalho de Melo total_len, flags); 21821da177e4SLinus Torvalds if (err < 0) 21831da177e4SLinus Torvalds goto out_freeiov; 21841da177e4SLinus Torvalds len = err; 21851da177e4SLinus Torvalds 21861da177e4SLinus Torvalds if (uaddr != NULL) { 218743db362dSMaciej Żenczykowski err = move_addr_to_user(&addr, 2188a2e27255SArnaldo Carvalho de Melo msg_sys->msg_namelen, uaddr, 218989bddce5SStephen Hemminger uaddr_len); 21901da177e4SLinus Torvalds if (err < 0) 21911da177e4SLinus Torvalds goto out_freeiov; 21921da177e4SLinus Torvalds } 2193a2e27255SArnaldo Carvalho de Melo err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT), 219437f7f421SDavid S. Miller COMPAT_FLAGS(msg)); 21951da177e4SLinus Torvalds if (err) 21961da177e4SLinus Torvalds goto out_freeiov; 21971da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) 2198a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 21991da177e4SLinus Torvalds &msg_compat->msg_controllen); 22001da177e4SLinus Torvalds else 2201a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 22021da177e4SLinus Torvalds &msg->msg_controllen); 22031da177e4SLinus Torvalds if (err) 22041da177e4SLinus Torvalds goto out_freeiov; 22051da177e4SLinus Torvalds err = len; 22061da177e4SLinus Torvalds 22071da177e4SLinus Torvalds out_freeiov: 22081da177e4SLinus Torvalds if (iov != iovstack) 2209a74e9106SEric Dumazet kfree(iov); 2210a2e27255SArnaldo Carvalho de Melo return err; 2211a2e27255SArnaldo Carvalho de Melo } 2212a2e27255SArnaldo Carvalho de Melo 2213a2e27255SArnaldo Carvalho de Melo /* 2214a2e27255SArnaldo Carvalho de Melo * BSD recvmsg interface 2215a2e27255SArnaldo Carvalho de Melo */ 2216a2e27255SArnaldo Carvalho de Melo 2217666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags) 2218a2e27255SArnaldo Carvalho de Melo { 2219a2e27255SArnaldo Carvalho de Melo int fput_needed, err; 2220a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 22211be374a0SAndy Lutomirski struct socket *sock; 2222a2e27255SArnaldo Carvalho de Melo 22231be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2224a2e27255SArnaldo Carvalho de Melo if (!sock) 2225a2e27255SArnaldo Carvalho de Melo goto out; 2226a2e27255SArnaldo Carvalho de Melo 2227a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2228a2e27255SArnaldo Carvalho de Melo 22296cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 22301da177e4SLinus Torvalds out: 22311da177e4SLinus Torvalds return err; 22321da177e4SLinus Torvalds } 22331da177e4SLinus Torvalds 2234666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg, 2235a7526eb5SAndy Lutomirski unsigned int, flags) 2236a7526eb5SAndy Lutomirski { 2237a7526eb5SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 2238a7526eb5SAndy Lutomirski return -EINVAL; 2239a7526eb5SAndy Lutomirski return __sys_recvmsg(fd, msg, flags); 2240a7526eb5SAndy Lutomirski } 2241a7526eb5SAndy Lutomirski 2242a2e27255SArnaldo Carvalho de Melo /* 2243a2e27255SArnaldo Carvalho de Melo * Linux recvmmsg interface 2244a2e27255SArnaldo Carvalho de Melo */ 22451da177e4SLinus Torvalds 2246a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2247a2e27255SArnaldo Carvalho de Melo unsigned int flags, struct timespec *timeout) 2248a2e27255SArnaldo Carvalho de Melo { 2249a2e27255SArnaldo Carvalho de Melo int fput_needed, err, datagrams; 2250a2e27255SArnaldo Carvalho de Melo struct socket *sock; 2251a2e27255SArnaldo Carvalho de Melo struct mmsghdr __user *entry; 2252d7256d0eSJean-Mickael Guerin struct compat_mmsghdr __user *compat_entry; 2253a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2254a2e27255SArnaldo Carvalho de Melo struct timespec end_time; 2255a2e27255SArnaldo Carvalho de Melo 2256a2e27255SArnaldo Carvalho de Melo if (timeout && 2257a2e27255SArnaldo Carvalho de Melo poll_select_set_timeout(&end_time, timeout->tv_sec, 2258a2e27255SArnaldo Carvalho de Melo timeout->tv_nsec)) 2259a2e27255SArnaldo Carvalho de Melo return -EINVAL; 2260a2e27255SArnaldo Carvalho de Melo 2261a2e27255SArnaldo Carvalho de Melo datagrams = 0; 2262a2e27255SArnaldo Carvalho de Melo 2263a2e27255SArnaldo Carvalho de Melo sock = sockfd_lookup_light(fd, &err, &fput_needed); 2264a2e27255SArnaldo Carvalho de Melo if (!sock) 2265a2e27255SArnaldo Carvalho de Melo return err; 2266a2e27255SArnaldo Carvalho de Melo 2267a2e27255SArnaldo Carvalho de Melo err = sock_error(sock->sk); 2268a2e27255SArnaldo Carvalho de Melo if (err) 2269a2e27255SArnaldo Carvalho de Melo goto out_put; 2270a2e27255SArnaldo Carvalho de Melo 2271a2e27255SArnaldo Carvalho de Melo entry = mmsg; 2272d7256d0eSJean-Mickael Guerin compat_entry = (struct compat_mmsghdr __user *)mmsg; 2273a2e27255SArnaldo Carvalho de Melo 2274a2e27255SArnaldo Carvalho de Melo while (datagrams < vlen) { 2275a2e27255SArnaldo Carvalho de Melo /* 2276a2e27255SArnaldo Carvalho de Melo * No need to ask LSM for more than the first datagram. 2277a2e27255SArnaldo Carvalho de Melo */ 2278d7256d0eSJean-Mickael Guerin if (MSG_CMSG_COMPAT & flags) { 2279666547ffSAl Viro err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry, 2280b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2281b9eb8b87SAnton Blanchard datagrams); 2282d7256d0eSJean-Mickael Guerin if (err < 0) 2283d7256d0eSJean-Mickael Guerin break; 2284d7256d0eSJean-Mickael Guerin err = __put_user(err, &compat_entry->msg_len); 2285d7256d0eSJean-Mickael Guerin ++compat_entry; 2286d7256d0eSJean-Mickael Guerin } else { 2287a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, 2288666547ffSAl Viro (struct user_msghdr __user *)entry, 2289b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2290b9eb8b87SAnton Blanchard datagrams); 2291a2e27255SArnaldo Carvalho de Melo if (err < 0) 2292a2e27255SArnaldo Carvalho de Melo break; 2293a2e27255SArnaldo Carvalho de Melo err = put_user(err, &entry->msg_len); 2294d7256d0eSJean-Mickael Guerin ++entry; 2295d7256d0eSJean-Mickael Guerin } 2296d7256d0eSJean-Mickael Guerin 2297a2e27255SArnaldo Carvalho de Melo if (err) 2298a2e27255SArnaldo Carvalho de Melo break; 2299a2e27255SArnaldo Carvalho de Melo ++datagrams; 2300a2e27255SArnaldo Carvalho de Melo 230171c5c159SBrandon L Black /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ 230271c5c159SBrandon L Black if (flags & MSG_WAITFORONE) 230371c5c159SBrandon L Black flags |= MSG_DONTWAIT; 230471c5c159SBrandon L Black 2305a2e27255SArnaldo Carvalho de Melo if (timeout) { 2306a2e27255SArnaldo Carvalho de Melo ktime_get_ts(timeout); 2307a2e27255SArnaldo Carvalho de Melo *timeout = timespec_sub(end_time, *timeout); 2308a2e27255SArnaldo Carvalho de Melo if (timeout->tv_sec < 0) { 2309a2e27255SArnaldo Carvalho de Melo timeout->tv_sec = timeout->tv_nsec = 0; 2310a2e27255SArnaldo Carvalho de Melo break; 2311a2e27255SArnaldo Carvalho de Melo } 2312a2e27255SArnaldo Carvalho de Melo 2313a2e27255SArnaldo Carvalho de Melo /* Timeout, return less than vlen datagrams */ 2314a2e27255SArnaldo Carvalho de Melo if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) 2315a2e27255SArnaldo Carvalho de Melo break; 2316a2e27255SArnaldo Carvalho de Melo } 2317a2e27255SArnaldo Carvalho de Melo 2318a2e27255SArnaldo Carvalho de Melo /* Out of band data, return right away */ 2319a2e27255SArnaldo Carvalho de Melo if (msg_sys.msg_flags & MSG_OOB) 2320a2e27255SArnaldo Carvalho de Melo break; 2321a2e27255SArnaldo Carvalho de Melo } 2322a2e27255SArnaldo Carvalho de Melo 2323a2e27255SArnaldo Carvalho de Melo out_put: 2324a2e27255SArnaldo Carvalho de Melo fput_light(sock->file, fput_needed); 2325a2e27255SArnaldo Carvalho de Melo 2326a2e27255SArnaldo Carvalho de Melo if (err == 0) 2327a2e27255SArnaldo Carvalho de Melo return datagrams; 2328a2e27255SArnaldo Carvalho de Melo 2329a2e27255SArnaldo Carvalho de Melo if (datagrams != 0) { 2330a2e27255SArnaldo Carvalho de Melo /* 2331a2e27255SArnaldo Carvalho de Melo * We may return less entries than requested (vlen) if the 2332a2e27255SArnaldo Carvalho de Melo * sock is non block and there aren't enough datagrams... 2333a2e27255SArnaldo Carvalho de Melo */ 2334a2e27255SArnaldo Carvalho de Melo if (err != -EAGAIN) { 2335a2e27255SArnaldo Carvalho de Melo /* 2336a2e27255SArnaldo Carvalho de Melo * ... or if recvmsg returns an error after we 2337a2e27255SArnaldo Carvalho de Melo * received some datagrams, where we record the 2338a2e27255SArnaldo Carvalho de Melo * error to return on the next call or if the 2339a2e27255SArnaldo Carvalho de Melo * app asks about it using getsockopt(SO_ERROR). 2340a2e27255SArnaldo Carvalho de Melo */ 2341a2e27255SArnaldo Carvalho de Melo sock->sk->sk_err = -err; 2342a2e27255SArnaldo Carvalho de Melo } 2343a2e27255SArnaldo Carvalho de Melo 2344a2e27255SArnaldo Carvalho de Melo return datagrams; 2345a2e27255SArnaldo Carvalho de Melo } 2346a2e27255SArnaldo Carvalho de Melo 2347a2e27255SArnaldo Carvalho de Melo return err; 2348a2e27255SArnaldo Carvalho de Melo } 2349a2e27255SArnaldo Carvalho de Melo 2350a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, 2351a2e27255SArnaldo Carvalho de Melo unsigned int, vlen, unsigned int, flags, 2352a2e27255SArnaldo Carvalho de Melo struct timespec __user *, timeout) 2353a2e27255SArnaldo Carvalho de Melo { 2354a2e27255SArnaldo Carvalho de Melo int datagrams; 2355a2e27255SArnaldo Carvalho de Melo struct timespec timeout_sys; 2356a2e27255SArnaldo Carvalho de Melo 23571be374a0SAndy Lutomirski if (flags & MSG_CMSG_COMPAT) 23581be374a0SAndy Lutomirski return -EINVAL; 23591be374a0SAndy Lutomirski 2360a2e27255SArnaldo Carvalho de Melo if (!timeout) 2361a2e27255SArnaldo Carvalho de Melo return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); 2362a2e27255SArnaldo Carvalho de Melo 2363a2e27255SArnaldo Carvalho de Melo if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys))) 2364a2e27255SArnaldo Carvalho de Melo return -EFAULT; 2365a2e27255SArnaldo Carvalho de Melo 2366a2e27255SArnaldo Carvalho de Melo datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys); 2367a2e27255SArnaldo Carvalho de Melo 2368a2e27255SArnaldo Carvalho de Melo if (datagrams > 0 && 2369a2e27255SArnaldo Carvalho de Melo copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys))) 2370a2e27255SArnaldo Carvalho de Melo datagrams = -EFAULT; 2371a2e27255SArnaldo Carvalho de Melo 2372a2e27255SArnaldo Carvalho de Melo return datagrams; 2373a2e27255SArnaldo Carvalho de Melo } 2374a2e27255SArnaldo Carvalho de Melo 2375a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL 23761da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */ 23771da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long)) 2378228e548eSAnton Blanchard static const unsigned char nargs[21] = { 237989bddce5SStephen Hemminger AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 23801da177e4SLinus Torvalds AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 2381aaca0bdcSUlrich Drepper AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 2382228e548eSAnton Blanchard AL(4), AL(5), AL(4) 238389bddce5SStephen Hemminger }; 238489bddce5SStephen Hemminger 23851da177e4SLinus Torvalds #undef AL 23861da177e4SLinus Torvalds 23871da177e4SLinus Torvalds /* 23881da177e4SLinus Torvalds * System call vectors. 23891da177e4SLinus Torvalds * 23901da177e4SLinus Torvalds * Argument checking cleaned up. Saved 20% in size. 23911da177e4SLinus Torvalds * This function doesn't need to set the kernel lock because 23921da177e4SLinus Torvalds * it is set by the callees. 23931da177e4SLinus Torvalds */ 23941da177e4SLinus Torvalds 23953e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) 23961da177e4SLinus Torvalds { 23972950fa9dSChen Gang unsigned long a[AUDITSC_ARGS]; 23981da177e4SLinus Torvalds unsigned long a0, a1; 23991da177e4SLinus Torvalds int err; 240047379052SArjan van de Ven unsigned int len; 24011da177e4SLinus Torvalds 2402228e548eSAnton Blanchard if (call < 1 || call > SYS_SENDMMSG) 24031da177e4SLinus Torvalds return -EINVAL; 24041da177e4SLinus Torvalds 240547379052SArjan van de Ven len = nargs[call]; 240647379052SArjan van de Ven if (len > sizeof(a)) 240747379052SArjan van de Ven return -EINVAL; 240847379052SArjan van de Ven 24091da177e4SLinus Torvalds /* copy_from_user should be SMP safe. */ 241047379052SArjan van de Ven if (copy_from_user(a, args, len)) 24111da177e4SLinus Torvalds return -EFAULT; 24121da177e4SLinus Torvalds 24132950fa9dSChen Gang err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); 24142950fa9dSChen Gang if (err) 24152950fa9dSChen Gang return err; 24163ec3b2fbSDavid Woodhouse 24171da177e4SLinus Torvalds a0 = a[0]; 24181da177e4SLinus Torvalds a1 = a[1]; 24191da177e4SLinus Torvalds 242089bddce5SStephen Hemminger switch (call) { 24211da177e4SLinus Torvalds case SYS_SOCKET: 24221da177e4SLinus Torvalds err = sys_socket(a0, a1, a[2]); 24231da177e4SLinus Torvalds break; 24241da177e4SLinus Torvalds case SYS_BIND: 24251da177e4SLinus Torvalds err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]); 24261da177e4SLinus Torvalds break; 24271da177e4SLinus Torvalds case SYS_CONNECT: 24281da177e4SLinus Torvalds err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]); 24291da177e4SLinus Torvalds break; 24301da177e4SLinus Torvalds case SYS_LISTEN: 24311da177e4SLinus Torvalds err = sys_listen(a0, a1); 24321da177e4SLinus Torvalds break; 24331da177e4SLinus Torvalds case SYS_ACCEPT: 2434de11defeSUlrich Drepper err = sys_accept4(a0, (struct sockaddr __user *)a1, 2435aaca0bdcSUlrich Drepper (int __user *)a[2], 0); 24361da177e4SLinus Torvalds break; 24371da177e4SLinus Torvalds case SYS_GETSOCKNAME: 243889bddce5SStephen Hemminger err = 243989bddce5SStephen Hemminger sys_getsockname(a0, (struct sockaddr __user *)a1, 244089bddce5SStephen Hemminger (int __user *)a[2]); 24411da177e4SLinus Torvalds break; 24421da177e4SLinus Torvalds case SYS_GETPEERNAME: 244389bddce5SStephen Hemminger err = 244489bddce5SStephen Hemminger sys_getpeername(a0, (struct sockaddr __user *)a1, 244589bddce5SStephen Hemminger (int __user *)a[2]); 24461da177e4SLinus Torvalds break; 24471da177e4SLinus Torvalds case SYS_SOCKETPAIR: 24481da177e4SLinus Torvalds err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]); 24491da177e4SLinus Torvalds break; 24501da177e4SLinus Torvalds case SYS_SEND: 24511da177e4SLinus Torvalds err = sys_send(a0, (void __user *)a1, a[2], a[3]); 24521da177e4SLinus Torvalds break; 24531da177e4SLinus Torvalds case SYS_SENDTO: 24541da177e4SLinus Torvalds err = sys_sendto(a0, (void __user *)a1, a[2], a[3], 24551da177e4SLinus Torvalds (struct sockaddr __user *)a[4], a[5]); 24561da177e4SLinus Torvalds break; 24571da177e4SLinus Torvalds case SYS_RECV: 24581da177e4SLinus Torvalds err = sys_recv(a0, (void __user *)a1, a[2], a[3]); 24591da177e4SLinus Torvalds break; 24601da177e4SLinus Torvalds case SYS_RECVFROM: 24611da177e4SLinus Torvalds err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 246289bddce5SStephen Hemminger (struct sockaddr __user *)a[4], 246389bddce5SStephen Hemminger (int __user *)a[5]); 24641da177e4SLinus Torvalds break; 24651da177e4SLinus Torvalds case SYS_SHUTDOWN: 24661da177e4SLinus Torvalds err = sys_shutdown(a0, a1); 24671da177e4SLinus Torvalds break; 24681da177e4SLinus Torvalds case SYS_SETSOCKOPT: 24691da177e4SLinus Torvalds err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]); 24701da177e4SLinus Torvalds break; 24711da177e4SLinus Torvalds case SYS_GETSOCKOPT: 247289bddce5SStephen Hemminger err = 247389bddce5SStephen Hemminger sys_getsockopt(a0, a1, a[2], (char __user *)a[3], 247489bddce5SStephen Hemminger (int __user *)a[4]); 24751da177e4SLinus Torvalds break; 24761da177e4SLinus Torvalds case SYS_SENDMSG: 2477666547ffSAl Viro err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]); 24781da177e4SLinus Torvalds break; 2479228e548eSAnton Blanchard case SYS_SENDMMSG: 2480228e548eSAnton Blanchard err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); 2481228e548eSAnton Blanchard break; 24821da177e4SLinus Torvalds case SYS_RECVMSG: 2483666547ffSAl Viro err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]); 24841da177e4SLinus Torvalds break; 2485a2e27255SArnaldo Carvalho de Melo case SYS_RECVMMSG: 2486a2e27255SArnaldo Carvalho de Melo err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], 2487a2e27255SArnaldo Carvalho de Melo (struct timespec __user *)a[4]); 2488a2e27255SArnaldo Carvalho de Melo break; 2489de11defeSUlrich Drepper case SYS_ACCEPT4: 2490de11defeSUlrich Drepper err = sys_accept4(a0, (struct sockaddr __user *)a1, 2491de11defeSUlrich Drepper (int __user *)a[2], a[3]); 2492aaca0bdcSUlrich Drepper break; 24931da177e4SLinus Torvalds default: 24941da177e4SLinus Torvalds err = -EINVAL; 24951da177e4SLinus Torvalds break; 24961da177e4SLinus Torvalds } 24971da177e4SLinus Torvalds return err; 24981da177e4SLinus Torvalds } 24991da177e4SLinus Torvalds 25001da177e4SLinus Torvalds #endif /* __ARCH_WANT_SYS_SOCKETCALL */ 25011da177e4SLinus Torvalds 250255737fdaSStephen Hemminger /** 250355737fdaSStephen Hemminger * sock_register - add a socket protocol handler 250455737fdaSStephen Hemminger * @ops: description of protocol 250555737fdaSStephen Hemminger * 25061da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 25071da177e4SLinus Torvalds * advertise its address family, and have it linked into the 2508e793c0f7SMasanari Iida * socket interface. The value ops->family corresponds to the 250955737fdaSStephen Hemminger * socket system call protocol family. 25101da177e4SLinus Torvalds */ 2511f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops) 25121da177e4SLinus Torvalds { 25131da177e4SLinus Torvalds int err; 25141da177e4SLinus Torvalds 25151da177e4SLinus Torvalds if (ops->family >= NPROTO) { 25163410f22eSYang Yingliang pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO); 25171da177e4SLinus Torvalds return -ENOBUFS; 25181da177e4SLinus Torvalds } 251955737fdaSStephen Hemminger 252055737fdaSStephen Hemminger spin_lock(&net_family_lock); 2521190683a9SEric Dumazet if (rcu_dereference_protected(net_families[ops->family], 2522190683a9SEric Dumazet lockdep_is_held(&net_family_lock))) 25231da177e4SLinus Torvalds err = -EEXIST; 252455737fdaSStephen Hemminger else { 2525cf778b00SEric Dumazet rcu_assign_pointer(net_families[ops->family], ops); 25261da177e4SLinus Torvalds err = 0; 25271da177e4SLinus Torvalds } 252855737fdaSStephen Hemminger spin_unlock(&net_family_lock); 252955737fdaSStephen Hemminger 25303410f22eSYang Yingliang pr_info("NET: Registered protocol family %d\n", ops->family); 25311da177e4SLinus Torvalds return err; 25321da177e4SLinus Torvalds } 2533c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register); 25341da177e4SLinus Torvalds 253555737fdaSStephen Hemminger /** 253655737fdaSStephen Hemminger * sock_unregister - remove a protocol handler 253755737fdaSStephen Hemminger * @family: protocol family to remove 253855737fdaSStephen Hemminger * 25391da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 25401da177e4SLinus Torvalds * remove its address family, and have it unlinked from the 254155737fdaSStephen Hemminger * new socket creation. 254255737fdaSStephen Hemminger * 254355737fdaSStephen Hemminger * If protocol handler is a module, then it can use module reference 254455737fdaSStephen Hemminger * counts to protect against new references. If protocol handler is not 254555737fdaSStephen Hemminger * a module then it needs to provide its own protection in 254655737fdaSStephen Hemminger * the ops->create routine. 25471da177e4SLinus Torvalds */ 2548f0fd27d4SStephen Hemminger void sock_unregister(int family) 25491da177e4SLinus Torvalds { 2550f0fd27d4SStephen Hemminger BUG_ON(family < 0 || family >= NPROTO); 25511da177e4SLinus Torvalds 255255737fdaSStephen Hemminger spin_lock(&net_family_lock); 2553a9b3cd7fSStephen Hemminger RCU_INIT_POINTER(net_families[family], NULL); 255455737fdaSStephen Hemminger spin_unlock(&net_family_lock); 255555737fdaSStephen Hemminger 255655737fdaSStephen Hemminger synchronize_rcu(); 255755737fdaSStephen Hemminger 25583410f22eSYang Yingliang pr_info("NET: Unregistered protocol family %d\n", family); 25591da177e4SLinus Torvalds } 2560c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister); 25611da177e4SLinus Torvalds 256277d76ea3SAndi Kleen static int __init sock_init(void) 25631da177e4SLinus Torvalds { 2564b3e19d92SNick Piggin int err; 25652ca794e5SEric W. Biederman /* 25662ca794e5SEric W. Biederman * Initialize the network sysctl infrastructure. 25672ca794e5SEric W. Biederman */ 25682ca794e5SEric W. Biederman err = net_sysctl_init(); 25692ca794e5SEric W. Biederman if (err) 25702ca794e5SEric W. Biederman goto out; 2571b3e19d92SNick Piggin 25721da177e4SLinus Torvalds /* 25731da177e4SLinus Torvalds * Initialize skbuff SLAB cache 25741da177e4SLinus Torvalds */ 25751da177e4SLinus Torvalds skb_init(); 25761da177e4SLinus Torvalds 25771da177e4SLinus Torvalds /* 25781da177e4SLinus Torvalds * Initialize the protocols module. 25791da177e4SLinus Torvalds */ 25801da177e4SLinus Torvalds 25811da177e4SLinus Torvalds init_inodecache(); 2582b3e19d92SNick Piggin 2583b3e19d92SNick Piggin err = register_filesystem(&sock_fs_type); 2584b3e19d92SNick Piggin if (err) 2585b3e19d92SNick Piggin goto out_fs; 25861da177e4SLinus Torvalds sock_mnt = kern_mount(&sock_fs_type); 2587b3e19d92SNick Piggin if (IS_ERR(sock_mnt)) { 2588b3e19d92SNick Piggin err = PTR_ERR(sock_mnt); 2589b3e19d92SNick Piggin goto out_mount; 2590b3e19d92SNick Piggin } 259177d76ea3SAndi Kleen 259277d76ea3SAndi Kleen /* The real protocol initialization is performed in later initcalls. 25931da177e4SLinus Torvalds */ 25941da177e4SLinus Torvalds 25951da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER 25966d11cfdbSPablo Neira Ayuso err = netfilter_init(); 25976d11cfdbSPablo Neira Ayuso if (err) 25986d11cfdbSPablo Neira Ayuso goto out; 25991da177e4SLinus Torvalds #endif 2600cbeb321aSDavid S. Miller 2601408eccceSDaniel Borkmann ptp_classifier_init(); 2602c1f19b51SRichard Cochran 2603b3e19d92SNick Piggin out: 2604b3e19d92SNick Piggin return err; 2605b3e19d92SNick Piggin 2606b3e19d92SNick Piggin out_mount: 2607b3e19d92SNick Piggin unregister_filesystem(&sock_fs_type); 2608b3e19d92SNick Piggin out_fs: 2609b3e19d92SNick Piggin goto out; 26101da177e4SLinus Torvalds } 26111da177e4SLinus Torvalds 261277d76ea3SAndi Kleen core_initcall(sock_init); /* early initcall */ 261377d76ea3SAndi Kleen 26141da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 26151da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq) 26161da177e4SLinus Torvalds { 26171da177e4SLinus Torvalds int cpu; 26181da177e4SLinus Torvalds int counter = 0; 26191da177e4SLinus Torvalds 26206f912042SKAMEZAWA Hiroyuki for_each_possible_cpu(cpu) 26211da177e4SLinus Torvalds counter += per_cpu(sockets_in_use, cpu); 26221da177e4SLinus Torvalds 26231da177e4SLinus Torvalds /* It can be negative, by the way. 8) */ 26241da177e4SLinus Torvalds if (counter < 0) 26251da177e4SLinus Torvalds counter = 0; 26261da177e4SLinus Torvalds 26271da177e4SLinus Torvalds seq_printf(seq, "sockets: used %d\n", counter); 26281da177e4SLinus Torvalds } 26291da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */ 26301da177e4SLinus Torvalds 263189bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 26326b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock, 2633644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 26347a229387SArnd Bergmann { 26357a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 26367a229387SArnd Bergmann struct timeval ktv; 26377a229387SArnd Bergmann int err; 26387a229387SArnd Bergmann 26397a229387SArnd Bergmann set_fs(KERNEL_DS); 26406b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); 26417a229387SArnd Bergmann set_fs(old_fs); 2642644595f8SH. Peter Anvin if (!err) 2643ed6fe9d6SMikulas Patocka err = compat_put_timeval(&ktv, up); 2644644595f8SH. Peter Anvin 26457a229387SArnd Bergmann return err; 26467a229387SArnd Bergmann } 26477a229387SArnd Bergmann 26486b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock, 2649644595f8SH. Peter Anvin unsigned int cmd, void __user *up) 26507a229387SArnd Bergmann { 26517a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 26527a229387SArnd Bergmann struct timespec kts; 26537a229387SArnd Bergmann int err; 26547a229387SArnd Bergmann 26557a229387SArnd Bergmann set_fs(KERNEL_DS); 26566b96018bSArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); 26577a229387SArnd Bergmann set_fs(old_fs); 2658644595f8SH. Peter Anvin if (!err) 2659ed6fe9d6SMikulas Patocka err = compat_put_timespec(&kts, up); 2660644595f8SH. Peter Anvin 26617a229387SArnd Bergmann return err; 26627a229387SArnd Bergmann } 26637a229387SArnd Bergmann 26646b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32) 26657a229387SArnd Bergmann { 26667a229387SArnd Bergmann struct ifreq __user *uifr; 26677a229387SArnd Bergmann int err; 26687a229387SArnd Bergmann 26697a229387SArnd Bergmann uifr = compat_alloc_user_space(sizeof(struct ifreq)); 26706b96018bSArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 26717a229387SArnd Bergmann return -EFAULT; 26727a229387SArnd Bergmann 26736b96018bSArnd Bergmann err = dev_ioctl(net, SIOCGIFNAME, uifr); 26747a229387SArnd Bergmann if (err) 26757a229387SArnd Bergmann return err; 26767a229387SArnd Bergmann 26776b96018bSArnd Bergmann if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq))) 26787a229387SArnd Bergmann return -EFAULT; 26797a229387SArnd Bergmann 26807a229387SArnd Bergmann return 0; 26817a229387SArnd Bergmann } 26827a229387SArnd Bergmann 26836b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) 26847a229387SArnd Bergmann { 26856b96018bSArnd Bergmann struct compat_ifconf ifc32; 26867a229387SArnd Bergmann struct ifconf ifc; 26877a229387SArnd Bergmann struct ifconf __user *uifc; 26886b96018bSArnd Bergmann struct compat_ifreq __user *ifr32; 26897a229387SArnd Bergmann struct ifreq __user *ifr; 26907a229387SArnd Bergmann unsigned int i, j; 26917a229387SArnd Bergmann int err; 26927a229387SArnd Bergmann 26936b96018bSArnd Bergmann if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) 26947a229387SArnd Bergmann return -EFAULT; 26957a229387SArnd Bergmann 269643da5f2eSMathias Krause memset(&ifc, 0, sizeof(ifc)); 26977a229387SArnd Bergmann if (ifc32.ifcbuf == 0) { 26987a229387SArnd Bergmann ifc32.ifc_len = 0; 26997a229387SArnd Bergmann ifc.ifc_len = 0; 27007a229387SArnd Bergmann ifc.ifc_req = NULL; 27017a229387SArnd Bergmann uifc = compat_alloc_user_space(sizeof(struct ifconf)); 27027a229387SArnd Bergmann } else { 27036b96018bSArnd Bergmann size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) * 27047a229387SArnd Bergmann sizeof(struct ifreq); 27057a229387SArnd Bergmann uifc = compat_alloc_user_space(sizeof(struct ifconf) + len); 27067a229387SArnd Bergmann ifc.ifc_len = len; 27077a229387SArnd Bergmann ifr = ifc.ifc_req = (void __user *)(uifc + 1); 27087a229387SArnd Bergmann ifr32 = compat_ptr(ifc32.ifcbuf); 27096b96018bSArnd Bergmann for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) { 27106b96018bSArnd Bergmann if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq))) 27117a229387SArnd Bergmann return -EFAULT; 27127a229387SArnd Bergmann ifr++; 27137a229387SArnd Bergmann ifr32++; 27147a229387SArnd Bergmann } 27157a229387SArnd Bergmann } 27167a229387SArnd Bergmann if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) 27177a229387SArnd Bergmann return -EFAULT; 27187a229387SArnd Bergmann 27196b96018bSArnd Bergmann err = dev_ioctl(net, SIOCGIFCONF, uifc); 27207a229387SArnd Bergmann if (err) 27217a229387SArnd Bergmann return err; 27227a229387SArnd Bergmann 27237a229387SArnd Bergmann if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) 27247a229387SArnd Bergmann return -EFAULT; 27257a229387SArnd Bergmann 27267a229387SArnd Bergmann ifr = ifc.ifc_req; 27277a229387SArnd Bergmann ifr32 = compat_ptr(ifc32.ifcbuf); 27287a229387SArnd Bergmann for (i = 0, j = 0; 27296b96018bSArnd Bergmann i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len; 27306b96018bSArnd Bergmann i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) { 27316b96018bSArnd Bergmann if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq))) 27327a229387SArnd Bergmann return -EFAULT; 27337a229387SArnd Bergmann ifr32++; 27347a229387SArnd Bergmann ifr++; 27357a229387SArnd Bergmann } 27367a229387SArnd Bergmann 27377a229387SArnd Bergmann if (ifc32.ifcbuf == 0) { 27387a229387SArnd Bergmann /* Translate from 64-bit structure multiple to 27397a229387SArnd Bergmann * a 32-bit one. 27407a229387SArnd Bergmann */ 27417a229387SArnd Bergmann i = ifc.ifc_len; 27426b96018bSArnd Bergmann i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq)); 27437a229387SArnd Bergmann ifc32.ifc_len = i; 27447a229387SArnd Bergmann } else { 27457a229387SArnd Bergmann ifc32.ifc_len = i; 27467a229387SArnd Bergmann } 27476b96018bSArnd Bergmann if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) 27487a229387SArnd Bergmann return -EFAULT; 27497a229387SArnd Bergmann 27507a229387SArnd Bergmann return 0; 27517a229387SArnd Bergmann } 27527a229387SArnd Bergmann 27536b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) 27547a229387SArnd Bergmann { 27553a7da39dSBen Hutchings struct compat_ethtool_rxnfc __user *compat_rxnfc; 27563a7da39dSBen Hutchings bool convert_in = false, convert_out = false; 27573a7da39dSBen Hutchings size_t buf_size = ALIGN(sizeof(struct ifreq), 8); 27583a7da39dSBen Hutchings struct ethtool_rxnfc __user *rxnfc; 27597a229387SArnd Bergmann struct ifreq __user *ifr; 27603a7da39dSBen Hutchings u32 rule_cnt = 0, actual_rule_cnt; 27613a7da39dSBen Hutchings u32 ethcmd; 27627a229387SArnd Bergmann u32 data; 27633a7da39dSBen Hutchings int ret; 27647a229387SArnd Bergmann 27657a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 27667a229387SArnd Bergmann return -EFAULT; 27677a229387SArnd Bergmann 27683a7da39dSBen Hutchings compat_rxnfc = compat_ptr(data); 27693a7da39dSBen Hutchings 27703a7da39dSBen Hutchings if (get_user(ethcmd, &compat_rxnfc->cmd)) 27717a229387SArnd Bergmann return -EFAULT; 27727a229387SArnd Bergmann 27733a7da39dSBen Hutchings /* Most ethtool structures are defined without padding. 27743a7da39dSBen Hutchings * Unfortunately struct ethtool_rxnfc is an exception. 27753a7da39dSBen Hutchings */ 27763a7da39dSBen Hutchings switch (ethcmd) { 27773a7da39dSBen Hutchings default: 27783a7da39dSBen Hutchings break; 27793a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLALL: 27803a7da39dSBen Hutchings /* Buffer size is variable */ 27813a7da39dSBen Hutchings if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) 27823a7da39dSBen Hutchings return -EFAULT; 27833a7da39dSBen Hutchings if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) 27843a7da39dSBen Hutchings return -ENOMEM; 27853a7da39dSBen Hutchings buf_size += rule_cnt * sizeof(u32); 27863a7da39dSBen Hutchings /* fall through */ 27873a7da39dSBen Hutchings case ETHTOOL_GRXRINGS: 27883a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLCNT: 27893a7da39dSBen Hutchings case ETHTOOL_GRXCLSRULE: 279055664f32SBen Hutchings case ETHTOOL_SRXCLSRLINS: 27913a7da39dSBen Hutchings convert_out = true; 27923a7da39dSBen Hutchings /* fall through */ 27933a7da39dSBen Hutchings case ETHTOOL_SRXCLSRLDEL: 27943a7da39dSBen Hutchings buf_size += sizeof(struct ethtool_rxnfc); 27953a7da39dSBen Hutchings convert_in = true; 27963a7da39dSBen Hutchings break; 27973a7da39dSBen Hutchings } 27983a7da39dSBen Hutchings 27993a7da39dSBen Hutchings ifr = compat_alloc_user_space(buf_size); 2800954b1244SStephen Hemminger rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8); 28013a7da39dSBen Hutchings 28023a7da39dSBen Hutchings if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 28033a7da39dSBen Hutchings return -EFAULT; 28043a7da39dSBen Hutchings 28053a7da39dSBen Hutchings if (put_user(convert_in ? rxnfc : compat_ptr(data), 28063a7da39dSBen Hutchings &ifr->ifr_ifru.ifru_data)) 28073a7da39dSBen Hutchings return -EFAULT; 28083a7da39dSBen Hutchings 28093a7da39dSBen Hutchings if (convert_in) { 2810127fe533SAlexander Duyck /* We expect there to be holes between fs.m_ext and 28113a7da39dSBen Hutchings * fs.ring_cookie and at the end of fs, but nowhere else. 28123a7da39dSBen Hutchings */ 2813127fe533SAlexander Duyck BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + 2814127fe533SAlexander Duyck sizeof(compat_rxnfc->fs.m_ext) != 2815127fe533SAlexander Duyck offsetof(struct ethtool_rxnfc, fs.m_ext) + 2816127fe533SAlexander Duyck sizeof(rxnfc->fs.m_ext)); 28173a7da39dSBen Hutchings BUILD_BUG_ON( 28183a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.location) - 28193a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != 28203a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.location) - 28213a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.ring_cookie)); 28223a7da39dSBen Hutchings 28233a7da39dSBen Hutchings if (copy_in_user(rxnfc, compat_rxnfc, 2824954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.m_ext + 1) - 2825954b1244SStephen Hemminger (void __user *)rxnfc) || 28263a7da39dSBen Hutchings copy_in_user(&rxnfc->fs.ring_cookie, 28273a7da39dSBen Hutchings &compat_rxnfc->fs.ring_cookie, 2828954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.location + 1) - 2829954b1244SStephen Hemminger (void __user *)&rxnfc->fs.ring_cookie) || 28303a7da39dSBen Hutchings copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt, 28313a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 28323a7da39dSBen Hutchings return -EFAULT; 28333a7da39dSBen Hutchings } 28343a7da39dSBen Hutchings 28353a7da39dSBen Hutchings ret = dev_ioctl(net, SIOCETHTOOL, ifr); 28363a7da39dSBen Hutchings if (ret) 28373a7da39dSBen Hutchings return ret; 28383a7da39dSBen Hutchings 28393a7da39dSBen Hutchings if (convert_out) { 28403a7da39dSBen Hutchings if (copy_in_user(compat_rxnfc, rxnfc, 2841954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.m_ext + 1) - 2842954b1244SStephen Hemminger (const void __user *)rxnfc) || 28433a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->fs.ring_cookie, 28443a7da39dSBen Hutchings &rxnfc->fs.ring_cookie, 2845954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.location + 1) - 2846954b1244SStephen Hemminger (const void __user *)&rxnfc->fs.ring_cookie) || 28473a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, 28483a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 28493a7da39dSBen Hutchings return -EFAULT; 28503a7da39dSBen Hutchings 28513a7da39dSBen Hutchings if (ethcmd == ETHTOOL_GRXCLSRLALL) { 28523a7da39dSBen Hutchings /* As an optimisation, we only copy the actual 28533a7da39dSBen Hutchings * number of rules that the underlying 28543a7da39dSBen Hutchings * function returned. Since Mallory might 28553a7da39dSBen Hutchings * change the rule count in user memory, we 28563a7da39dSBen Hutchings * check that it is less than the rule count 28573a7da39dSBen Hutchings * originally given (as the user buffer size), 28583a7da39dSBen Hutchings * which has been range-checked. 28593a7da39dSBen Hutchings */ 28603a7da39dSBen Hutchings if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) 28613a7da39dSBen Hutchings return -EFAULT; 28623a7da39dSBen Hutchings if (actual_rule_cnt < rule_cnt) 28633a7da39dSBen Hutchings rule_cnt = actual_rule_cnt; 28643a7da39dSBen Hutchings if (copy_in_user(&compat_rxnfc->rule_locs[0], 28653a7da39dSBen Hutchings &rxnfc->rule_locs[0], 28663a7da39dSBen Hutchings rule_cnt * sizeof(u32))) 28673a7da39dSBen Hutchings return -EFAULT; 28683a7da39dSBen Hutchings } 28693a7da39dSBen Hutchings } 28703a7da39dSBen Hutchings 28713a7da39dSBen Hutchings return 0; 28727a229387SArnd Bergmann } 28737a229387SArnd Bergmann 28747a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) 28757a50a240SArnd Bergmann { 28767a50a240SArnd Bergmann void __user *uptr; 28777a50a240SArnd Bergmann compat_uptr_t uptr32; 28787a50a240SArnd Bergmann struct ifreq __user *uifr; 28797a50a240SArnd Bergmann 28807a50a240SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 28817a50a240SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) 28827a50a240SArnd Bergmann return -EFAULT; 28837a50a240SArnd Bergmann 28847a50a240SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) 28857a50a240SArnd Bergmann return -EFAULT; 28867a50a240SArnd Bergmann 28877a50a240SArnd Bergmann uptr = compat_ptr(uptr32); 28887a50a240SArnd Bergmann 28897a50a240SArnd Bergmann if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc)) 28907a50a240SArnd Bergmann return -EFAULT; 28917a50a240SArnd Bergmann 28927a50a240SArnd Bergmann return dev_ioctl(net, SIOCWANDEV, uifr); 28937a50a240SArnd Bergmann } 28947a50a240SArnd Bergmann 28956b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd, 28966b96018bSArnd Bergmann struct compat_ifreq __user *ifr32) 28977a229387SArnd Bergmann { 28987a229387SArnd Bergmann struct ifreq kifr; 28997a229387SArnd Bergmann mm_segment_t old_fs; 29007a229387SArnd Bergmann int err; 29017a229387SArnd Bergmann 29027a229387SArnd Bergmann switch (cmd) { 29037a229387SArnd Bergmann case SIOCBONDENSLAVE: 29047a229387SArnd Bergmann case SIOCBONDRELEASE: 29057a229387SArnd Bergmann case SIOCBONDSETHWADDR: 29067a229387SArnd Bergmann case SIOCBONDCHANGEACTIVE: 29076b96018bSArnd Bergmann if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq))) 29087a229387SArnd Bergmann return -EFAULT; 29097a229387SArnd Bergmann 29107a229387SArnd Bergmann old_fs = get_fs(); 29117a229387SArnd Bergmann set_fs(KERNEL_DS); 2912c3f52ae6Sstephen hemminger err = dev_ioctl(net, cmd, 2913c3f52ae6Sstephen hemminger (struct ifreq __user __force *) &kifr); 29147a229387SArnd Bergmann set_fs(old_fs); 29157a229387SArnd Bergmann 29167a229387SArnd Bergmann return err; 29177a229387SArnd Bergmann default: 291807d106d0SLinus Torvalds return -ENOIOCTLCMD; 2919ccbd6a5aSJoe Perches } 29207a229387SArnd Bergmann } 29217a229387SArnd Bergmann 2922590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ 2923590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, 29246b96018bSArnd Bergmann struct compat_ifreq __user *u_ifreq32) 29257a229387SArnd Bergmann { 29267a229387SArnd Bergmann struct ifreq __user *u_ifreq64; 29277a229387SArnd Bergmann char tmp_buf[IFNAMSIZ]; 29287a229387SArnd Bergmann void __user *data64; 29297a229387SArnd Bergmann u32 data32; 29307a229387SArnd Bergmann 29317a229387SArnd Bergmann if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), 29327a229387SArnd Bergmann IFNAMSIZ)) 29337a229387SArnd Bergmann return -EFAULT; 2934417c3522SBen Hutchings if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) 29357a229387SArnd Bergmann return -EFAULT; 29367a229387SArnd Bergmann data64 = compat_ptr(data32); 29377a229387SArnd Bergmann 29387a229387SArnd Bergmann u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); 29397a229387SArnd Bergmann 29407a229387SArnd Bergmann if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], 29417a229387SArnd Bergmann IFNAMSIZ)) 29427a229387SArnd Bergmann return -EFAULT; 2943417c3522SBen Hutchings if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) 29447a229387SArnd Bergmann return -EFAULT; 29457a229387SArnd Bergmann 29466b96018bSArnd Bergmann return dev_ioctl(net, cmd, u_ifreq64); 29477a229387SArnd Bergmann } 29487a229387SArnd Bergmann 29496b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock, 29506b96018bSArnd Bergmann unsigned int cmd, struct compat_ifreq __user *uifr32) 29517a229387SArnd Bergmann { 2952a2116ed2SArnd Bergmann struct ifreq __user *uifr; 29537a229387SArnd Bergmann int err; 29547a229387SArnd Bergmann 2955a2116ed2SArnd Bergmann uifr = compat_alloc_user_space(sizeof(*uifr)); 2956a2116ed2SArnd Bergmann if (copy_in_user(uifr, uifr32, sizeof(*uifr32))) 29577a229387SArnd Bergmann return -EFAULT; 2958a2116ed2SArnd Bergmann 2959a2116ed2SArnd Bergmann err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr); 2960a2116ed2SArnd Bergmann 29617a229387SArnd Bergmann if (!err) { 29627a229387SArnd Bergmann switch (cmd) { 29637a229387SArnd Bergmann case SIOCGIFFLAGS: 29647a229387SArnd Bergmann case SIOCGIFMETRIC: 29657a229387SArnd Bergmann case SIOCGIFMTU: 29667a229387SArnd Bergmann case SIOCGIFMEM: 29677a229387SArnd Bergmann case SIOCGIFHWADDR: 29687a229387SArnd Bergmann case SIOCGIFINDEX: 29697a229387SArnd Bergmann case SIOCGIFADDR: 29707a229387SArnd Bergmann case SIOCGIFBRDADDR: 29717a229387SArnd Bergmann case SIOCGIFDSTADDR: 29727a229387SArnd Bergmann case SIOCGIFNETMASK: 2973fab2532bSArnd Bergmann case SIOCGIFPFLAGS: 29747a229387SArnd Bergmann case SIOCGIFTXQLEN: 2975fab2532bSArnd Bergmann case SIOCGMIIPHY: 2976fab2532bSArnd Bergmann case SIOCGMIIREG: 2977a2116ed2SArnd Bergmann if (copy_in_user(uifr32, uifr, sizeof(*uifr32))) 2978a2116ed2SArnd Bergmann err = -EFAULT; 29797a229387SArnd Bergmann break; 2980a2116ed2SArnd Bergmann } 2981a2116ed2SArnd Bergmann } 2982a2116ed2SArnd Bergmann return err; 2983a2116ed2SArnd Bergmann } 2984a2116ed2SArnd Bergmann 2985a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 2986a2116ed2SArnd Bergmann struct compat_ifreq __user *uifr32) 2987a2116ed2SArnd Bergmann { 2988a2116ed2SArnd Bergmann struct ifreq ifr; 2989a2116ed2SArnd Bergmann struct compat_ifmap __user *uifmap32; 2990a2116ed2SArnd Bergmann mm_segment_t old_fs; 2991a2116ed2SArnd Bergmann int err; 2992a2116ed2SArnd Bergmann 2993a2116ed2SArnd Bergmann uifmap32 = &uifr32->ifr_ifru.ifru_map; 2994a2116ed2SArnd Bergmann err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); 29953ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 29963ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 29973ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 29983ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.irq, &uifmap32->irq); 29993ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.dma, &uifmap32->dma); 30003ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.port, &uifmap32->port); 3001a2116ed2SArnd Bergmann if (err) 3002a2116ed2SArnd Bergmann return -EFAULT; 3003a2116ed2SArnd Bergmann 3004a2116ed2SArnd Bergmann old_fs = get_fs(); 3005a2116ed2SArnd Bergmann set_fs(KERNEL_DS); 3006c3f52ae6Sstephen hemminger err = dev_ioctl(net, cmd, (void __user __force *)&ifr); 3007a2116ed2SArnd Bergmann set_fs(old_fs); 3008a2116ed2SArnd Bergmann 3009a2116ed2SArnd Bergmann if (cmd == SIOCGIFMAP && !err) { 30107a229387SArnd Bergmann err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); 30113ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 30123ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 30133ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 30143ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.irq, &uifmap32->irq); 30153ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.dma, &uifmap32->dma); 30163ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.port, &uifmap32->port); 30177a229387SArnd Bergmann if (err) 30187a229387SArnd Bergmann err = -EFAULT; 30197a229387SArnd Bergmann } 30207a229387SArnd Bergmann return err; 30217a229387SArnd Bergmann } 30227a229387SArnd Bergmann 30237a229387SArnd Bergmann struct rtentry32 { 30247a229387SArnd Bergmann u32 rt_pad1; 30257a229387SArnd Bergmann struct sockaddr rt_dst; /* target address */ 30267a229387SArnd Bergmann struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ 30277a229387SArnd Bergmann struct sockaddr rt_genmask; /* target network mask (IP) */ 30287a229387SArnd Bergmann unsigned short rt_flags; 30297a229387SArnd Bergmann short rt_pad2; 30307a229387SArnd Bergmann u32 rt_pad3; 30317a229387SArnd Bergmann unsigned char rt_tos; 30327a229387SArnd Bergmann unsigned char rt_class; 30337a229387SArnd Bergmann short rt_pad4; 30347a229387SArnd Bergmann short rt_metric; /* +1 for binary compatibility! */ 30357a229387SArnd Bergmann /* char * */ u32 rt_dev; /* forcing the device at add */ 30367a229387SArnd Bergmann u32 rt_mtu; /* per route MTU/Window */ 30377a229387SArnd Bergmann u32 rt_window; /* Window clamping */ 30387a229387SArnd Bergmann unsigned short rt_irtt; /* Initial RTT */ 30397a229387SArnd Bergmann }; 30407a229387SArnd Bergmann 30417a229387SArnd Bergmann struct in6_rtmsg32 { 30427a229387SArnd Bergmann struct in6_addr rtmsg_dst; 30437a229387SArnd Bergmann struct in6_addr rtmsg_src; 30447a229387SArnd Bergmann struct in6_addr rtmsg_gateway; 30457a229387SArnd Bergmann u32 rtmsg_type; 30467a229387SArnd Bergmann u16 rtmsg_dst_len; 30477a229387SArnd Bergmann u16 rtmsg_src_len; 30487a229387SArnd Bergmann u32 rtmsg_metric; 30497a229387SArnd Bergmann u32 rtmsg_info; 30507a229387SArnd Bergmann u32 rtmsg_flags; 30517a229387SArnd Bergmann s32 rtmsg_ifindex; 30527a229387SArnd Bergmann }; 30537a229387SArnd Bergmann 30546b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock, 30556b96018bSArnd Bergmann unsigned int cmd, void __user *argp) 30567a229387SArnd Bergmann { 30577a229387SArnd Bergmann int ret; 30587a229387SArnd Bergmann void *r = NULL; 30597a229387SArnd Bergmann struct in6_rtmsg r6; 30607a229387SArnd Bergmann struct rtentry r4; 30617a229387SArnd Bergmann char devname[16]; 30627a229387SArnd Bergmann u32 rtdev; 30637a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 30647a229387SArnd Bergmann 30656b96018bSArnd Bergmann if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */ 30666b96018bSArnd Bergmann struct in6_rtmsg32 __user *ur6 = argp; 30677a229387SArnd Bergmann ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst), 30687a229387SArnd Bergmann 3 * sizeof(struct in6_addr)); 30693ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type)); 30703ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); 30713ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); 30723ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric)); 30733ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info)); 30743ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags)); 30753ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); 30767a229387SArnd Bergmann 30777a229387SArnd Bergmann r = (void *) &r6; 30787a229387SArnd Bergmann } else { /* ipv4 */ 30796b96018bSArnd Bergmann struct rtentry32 __user *ur4 = argp; 30807a229387SArnd Bergmann ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst), 30817a229387SArnd Bergmann 3 * sizeof(struct sockaddr)); 30823ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_flags, &(ur4->rt_flags)); 30833ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_metric, &(ur4->rt_metric)); 30843ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu)); 30853ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_window, &(ur4->rt_window)); 30863ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt)); 30873ddc5b46SMathieu Desnoyers ret |= get_user(rtdev, &(ur4->rt_dev)); 30887a229387SArnd Bergmann if (rtdev) { 30897a229387SArnd Bergmann ret |= copy_from_user(devname, compat_ptr(rtdev), 15); 3090c3f52ae6Sstephen hemminger r4.rt_dev = (char __user __force *)devname; 3091c3f52ae6Sstephen hemminger devname[15] = 0; 30927a229387SArnd Bergmann } else 30937a229387SArnd Bergmann r4.rt_dev = NULL; 30947a229387SArnd Bergmann 30957a229387SArnd Bergmann r = (void *) &r4; 30967a229387SArnd Bergmann } 30977a229387SArnd Bergmann 30987a229387SArnd Bergmann if (ret) { 30997a229387SArnd Bergmann ret = -EFAULT; 31007a229387SArnd Bergmann goto out; 31017a229387SArnd Bergmann } 31027a229387SArnd Bergmann 31037a229387SArnd Bergmann set_fs(KERNEL_DS); 31046b96018bSArnd Bergmann ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); 31057a229387SArnd Bergmann set_fs(old_fs); 31067a229387SArnd Bergmann 31077a229387SArnd Bergmann out: 31087a229387SArnd Bergmann return ret; 31097a229387SArnd Bergmann } 31107a229387SArnd Bergmann 31117a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE 31127a229387SArnd Bergmann * for some operations; this forces use of the newer bridge-utils that 311325985edcSLucas De Marchi * use compatible ioctls 31147a229387SArnd Bergmann */ 31156b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp) 31167a229387SArnd Bergmann { 31176b96018bSArnd Bergmann compat_ulong_t tmp; 31187a229387SArnd Bergmann 31196b96018bSArnd Bergmann if (get_user(tmp, argp)) 31207a229387SArnd Bergmann return -EFAULT; 31217a229387SArnd Bergmann if (tmp == BRCTL_GET_VERSION) 31227a229387SArnd Bergmann return BRCTL_VERSION + 1; 31237a229387SArnd Bergmann return -EINVAL; 31247a229387SArnd Bergmann } 31257a229387SArnd Bergmann 31266b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, 31276b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 31286b96018bSArnd Bergmann { 31296b96018bSArnd Bergmann void __user *argp = compat_ptr(arg); 31306b96018bSArnd Bergmann struct sock *sk = sock->sk; 31316b96018bSArnd Bergmann struct net *net = sock_net(sk); 31327a229387SArnd Bergmann 31336b96018bSArnd Bergmann if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 3134590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 31357a229387SArnd Bergmann 31366b96018bSArnd Bergmann switch (cmd) { 31376b96018bSArnd Bergmann case SIOCSIFBR: 31386b96018bSArnd Bergmann case SIOCGIFBR: 31396b96018bSArnd Bergmann return old_bridge_ioctl(argp); 31406b96018bSArnd Bergmann case SIOCGIFNAME: 31416b96018bSArnd Bergmann return dev_ifname32(net, argp); 31426b96018bSArnd Bergmann case SIOCGIFCONF: 31436b96018bSArnd Bergmann return dev_ifconf(net, argp); 31446b96018bSArnd Bergmann case SIOCETHTOOL: 31456b96018bSArnd Bergmann return ethtool_ioctl(net, argp); 31467a50a240SArnd Bergmann case SIOCWANDEV: 31477a50a240SArnd Bergmann return compat_siocwandev(net, argp); 3148a2116ed2SArnd Bergmann case SIOCGIFMAP: 3149a2116ed2SArnd Bergmann case SIOCSIFMAP: 3150a2116ed2SArnd Bergmann return compat_sioc_ifmap(net, cmd, argp); 31516b96018bSArnd Bergmann case SIOCBONDENSLAVE: 31526b96018bSArnd Bergmann case SIOCBONDRELEASE: 31536b96018bSArnd Bergmann case SIOCBONDSETHWADDR: 31546b96018bSArnd Bergmann case SIOCBONDCHANGEACTIVE: 31556b96018bSArnd Bergmann return bond_ioctl(net, cmd, argp); 31566b96018bSArnd Bergmann case SIOCADDRT: 31576b96018bSArnd Bergmann case SIOCDELRT: 31586b96018bSArnd Bergmann return routing_ioctl(net, sock, cmd, argp); 31596b96018bSArnd Bergmann case SIOCGSTAMP: 31606b96018bSArnd Bergmann return do_siocgstamp(net, sock, cmd, argp); 31616b96018bSArnd Bergmann case SIOCGSTAMPNS: 31626b96018bSArnd Bergmann return do_siocgstampns(net, sock, cmd, argp); 3163590d4693SBen Hutchings case SIOCBONDSLAVEINFOQUERY: 3164590d4693SBen Hutchings case SIOCBONDINFOQUERY: 3165a2116ed2SArnd Bergmann case SIOCSHWTSTAMP: 3166fd468c74SBen Hutchings case SIOCGHWTSTAMP: 3167590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 31687a229387SArnd Bergmann 31696b96018bSArnd Bergmann case FIOSETOWN: 31706b96018bSArnd Bergmann case SIOCSPGRP: 31716b96018bSArnd Bergmann case FIOGETOWN: 31726b96018bSArnd Bergmann case SIOCGPGRP: 31736b96018bSArnd Bergmann case SIOCBRADDBR: 31746b96018bSArnd Bergmann case SIOCBRDELBR: 31756b96018bSArnd Bergmann case SIOCGIFVLAN: 31766b96018bSArnd Bergmann case SIOCSIFVLAN: 31776b96018bSArnd Bergmann case SIOCADDDLCI: 31786b96018bSArnd Bergmann case SIOCDELDLCI: 31796b96018bSArnd Bergmann return sock_ioctl(file, cmd, arg); 31806b96018bSArnd Bergmann 31816b96018bSArnd Bergmann case SIOCGIFFLAGS: 31826b96018bSArnd Bergmann case SIOCSIFFLAGS: 31836b96018bSArnd Bergmann case SIOCGIFMETRIC: 31846b96018bSArnd Bergmann case SIOCSIFMETRIC: 31856b96018bSArnd Bergmann case SIOCGIFMTU: 31866b96018bSArnd Bergmann case SIOCSIFMTU: 31876b96018bSArnd Bergmann case SIOCGIFMEM: 31886b96018bSArnd Bergmann case SIOCSIFMEM: 31896b96018bSArnd Bergmann case SIOCGIFHWADDR: 31906b96018bSArnd Bergmann case SIOCSIFHWADDR: 31916b96018bSArnd Bergmann case SIOCADDMULTI: 31926b96018bSArnd Bergmann case SIOCDELMULTI: 31936b96018bSArnd Bergmann case SIOCGIFINDEX: 31946b96018bSArnd Bergmann case SIOCGIFADDR: 31956b96018bSArnd Bergmann case SIOCSIFADDR: 31966b96018bSArnd Bergmann case SIOCSIFHWBROADCAST: 31976b96018bSArnd Bergmann case SIOCDIFADDR: 31986b96018bSArnd Bergmann case SIOCGIFBRDADDR: 31996b96018bSArnd Bergmann case SIOCSIFBRDADDR: 32006b96018bSArnd Bergmann case SIOCGIFDSTADDR: 32016b96018bSArnd Bergmann case SIOCSIFDSTADDR: 32026b96018bSArnd Bergmann case SIOCGIFNETMASK: 32036b96018bSArnd Bergmann case SIOCSIFNETMASK: 32046b96018bSArnd Bergmann case SIOCSIFPFLAGS: 32056b96018bSArnd Bergmann case SIOCGIFPFLAGS: 32066b96018bSArnd Bergmann case SIOCGIFTXQLEN: 32076b96018bSArnd Bergmann case SIOCSIFTXQLEN: 32086b96018bSArnd Bergmann case SIOCBRADDIF: 32096b96018bSArnd Bergmann case SIOCBRDELIF: 32109177efd3SArnd Bergmann case SIOCSIFNAME: 32119177efd3SArnd Bergmann case SIOCGMIIPHY: 32129177efd3SArnd Bergmann case SIOCGMIIREG: 32139177efd3SArnd Bergmann case SIOCSMIIREG: 32146b96018bSArnd Bergmann return dev_ifsioc(net, sock, cmd, argp); 32159177efd3SArnd Bergmann 32166b96018bSArnd Bergmann case SIOCSARP: 32176b96018bSArnd Bergmann case SIOCGARP: 32186b96018bSArnd Bergmann case SIOCDARP: 32196b96018bSArnd Bergmann case SIOCATMARK: 32209177efd3SArnd Bergmann return sock_do_ioctl(net, sock, cmd, arg); 32219177efd3SArnd Bergmann } 32229177efd3SArnd Bergmann 32236b96018bSArnd Bergmann return -ENOIOCTLCMD; 32246b96018bSArnd Bergmann } 32257a229387SArnd Bergmann 322695c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd, 322789bbfc95SShaun Pereira unsigned long arg) 322889bbfc95SShaun Pereira { 322989bbfc95SShaun Pereira struct socket *sock = file->private_data; 323089bbfc95SShaun Pereira int ret = -ENOIOCTLCMD; 323187de87d5SDavid S. Miller struct sock *sk; 323287de87d5SDavid S. Miller struct net *net; 323387de87d5SDavid S. Miller 323487de87d5SDavid S. Miller sk = sock->sk; 323587de87d5SDavid S. Miller net = sock_net(sk); 323689bbfc95SShaun Pereira 323789bbfc95SShaun Pereira if (sock->ops->compat_ioctl) 323889bbfc95SShaun Pereira ret = sock->ops->compat_ioctl(sock, cmd, arg); 323989bbfc95SShaun Pereira 324087de87d5SDavid S. Miller if (ret == -ENOIOCTLCMD && 324187de87d5SDavid S. Miller (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) 324287de87d5SDavid S. Miller ret = compat_wext_handle_ioctl(net, cmd, arg); 324387de87d5SDavid S. Miller 32446b96018bSArnd Bergmann if (ret == -ENOIOCTLCMD) 32456b96018bSArnd Bergmann ret = compat_sock_ioctl_trans(file, sock, cmd, arg); 32466b96018bSArnd Bergmann 324789bbfc95SShaun Pereira return ret; 324889bbfc95SShaun Pereira } 324989bbfc95SShaun Pereira #endif 325089bbfc95SShaun Pereira 3251ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) 3252ac5a488eSSridhar Samudrala { 3253ac5a488eSSridhar Samudrala return sock->ops->bind(sock, addr, addrlen); 3254ac5a488eSSridhar Samudrala } 3255c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind); 3256ac5a488eSSridhar Samudrala 3257ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog) 3258ac5a488eSSridhar Samudrala { 3259ac5a488eSSridhar Samudrala return sock->ops->listen(sock, backlog); 3260ac5a488eSSridhar Samudrala } 3261c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen); 3262ac5a488eSSridhar Samudrala 3263ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags) 3264ac5a488eSSridhar Samudrala { 3265ac5a488eSSridhar Samudrala struct sock *sk = sock->sk; 3266ac5a488eSSridhar Samudrala int err; 3267ac5a488eSSridhar Samudrala 3268ac5a488eSSridhar Samudrala err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, 3269ac5a488eSSridhar Samudrala newsock); 3270ac5a488eSSridhar Samudrala if (err < 0) 3271ac5a488eSSridhar Samudrala goto done; 3272ac5a488eSSridhar Samudrala 3273ac5a488eSSridhar Samudrala err = sock->ops->accept(sock, *newsock, flags); 3274ac5a488eSSridhar Samudrala if (err < 0) { 3275ac5a488eSSridhar Samudrala sock_release(*newsock); 3276fa8705b0STony Battersby *newsock = NULL; 3277ac5a488eSSridhar Samudrala goto done; 3278ac5a488eSSridhar Samudrala } 3279ac5a488eSSridhar Samudrala 3280ac5a488eSSridhar Samudrala (*newsock)->ops = sock->ops; 32811b08534eSWei Yongjun __module_get((*newsock)->ops->owner); 3282ac5a488eSSridhar Samudrala 3283ac5a488eSSridhar Samudrala done: 3284ac5a488eSSridhar Samudrala return err; 3285ac5a488eSSridhar Samudrala } 3286c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept); 3287ac5a488eSSridhar Samudrala 3288ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, 3289ac5a488eSSridhar Samudrala int flags) 3290ac5a488eSSridhar Samudrala { 3291ac5a488eSSridhar Samudrala return sock->ops->connect(sock, addr, addrlen, flags); 3292ac5a488eSSridhar Samudrala } 3293c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect); 3294ac5a488eSSridhar Samudrala 3295ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr, 3296ac5a488eSSridhar Samudrala int *addrlen) 3297ac5a488eSSridhar Samudrala { 3298ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 0); 3299ac5a488eSSridhar Samudrala } 3300c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname); 3301ac5a488eSSridhar Samudrala 3302ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr, 3303ac5a488eSSridhar Samudrala int *addrlen) 3304ac5a488eSSridhar Samudrala { 3305ac5a488eSSridhar Samudrala return sock->ops->getname(sock, addr, addrlen, 1); 3306ac5a488eSSridhar Samudrala } 3307c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername); 3308ac5a488eSSridhar Samudrala 3309ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname, 3310ac5a488eSSridhar Samudrala char *optval, int *optlen) 3311ac5a488eSSridhar Samudrala { 3312ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3313fb8621bbSNamhyung Kim char __user *uoptval; 3314fb8621bbSNamhyung Kim int __user *uoptlen; 3315ac5a488eSSridhar Samudrala int err; 3316ac5a488eSSridhar Samudrala 3317fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3318fb8621bbSNamhyung Kim uoptlen = (int __user __force *) optlen; 3319fb8621bbSNamhyung Kim 3320ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3321ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3322fb8621bbSNamhyung Kim err = sock_getsockopt(sock, level, optname, uoptval, uoptlen); 3323ac5a488eSSridhar Samudrala else 3324fb8621bbSNamhyung Kim err = sock->ops->getsockopt(sock, level, optname, uoptval, 3325fb8621bbSNamhyung Kim uoptlen); 3326ac5a488eSSridhar Samudrala set_fs(oldfs); 3327ac5a488eSSridhar Samudrala return err; 3328ac5a488eSSridhar Samudrala } 3329c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt); 3330ac5a488eSSridhar Samudrala 3331ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname, 3332b7058842SDavid S. Miller char *optval, unsigned int optlen) 3333ac5a488eSSridhar Samudrala { 3334ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3335fb8621bbSNamhyung Kim char __user *uoptval; 3336ac5a488eSSridhar Samudrala int err; 3337ac5a488eSSridhar Samudrala 3338fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3339fb8621bbSNamhyung Kim 3340ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3341ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3342fb8621bbSNamhyung Kim err = sock_setsockopt(sock, level, optname, uoptval, optlen); 3343ac5a488eSSridhar Samudrala else 3344fb8621bbSNamhyung Kim err = sock->ops->setsockopt(sock, level, optname, uoptval, 3345ac5a488eSSridhar Samudrala optlen); 3346ac5a488eSSridhar Samudrala set_fs(oldfs); 3347ac5a488eSSridhar Samudrala return err; 3348ac5a488eSSridhar Samudrala } 3349c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt); 3350ac5a488eSSridhar Samudrala 3351ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset, 3352ac5a488eSSridhar Samudrala size_t size, int flags) 3353ac5a488eSSridhar Samudrala { 3354ac5a488eSSridhar Samudrala if (sock->ops->sendpage) 3355ac5a488eSSridhar Samudrala return sock->ops->sendpage(sock, page, offset, size, flags); 3356ac5a488eSSridhar Samudrala 3357ac5a488eSSridhar Samudrala return sock_no_sendpage(sock, page, offset, size, flags); 3358ac5a488eSSridhar Samudrala } 3359c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage); 3360ac5a488eSSridhar Samudrala 3361ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg) 3362ac5a488eSSridhar Samudrala { 3363ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3364ac5a488eSSridhar Samudrala int err; 3365ac5a488eSSridhar Samudrala 3366ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3367ac5a488eSSridhar Samudrala err = sock->ops->ioctl(sock, cmd, arg); 3368ac5a488eSSridhar Samudrala set_fs(oldfs); 3369ac5a488eSSridhar Samudrala 3370ac5a488eSSridhar Samudrala return err; 3371ac5a488eSSridhar Samudrala } 3372c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl); 3373ac5a488eSSridhar Samudrala 337491cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) 337591cf45f0STrond Myklebust { 337691cf45f0STrond Myklebust return sock->ops->shutdown(sock, how); 337791cf45f0STrond Myklebust } 337891cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown); 3379