12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * NET An implementation of the SOCKET network access protocol. 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Version: @(#)socket.c 1.1.93 18/02/95 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Authors: Orest Zborowski, <obz@Kodak.COM> 802c30a84SJesper Juhl * Ross Biro 91da177e4SLinus Torvalds * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * Fixes: 121da177e4SLinus Torvalds * Anonymous : NOTSOCK/BADF cleanup. Error fix in 131da177e4SLinus Torvalds * shutdown() 141da177e4SLinus Torvalds * Alan Cox : verify_area() fixes 151da177e4SLinus Torvalds * Alan Cox : Removed DDI 161da177e4SLinus Torvalds * Jonathan Kamens : SOCK_DGRAM reconnect bug 171da177e4SLinus Torvalds * Alan Cox : Moved a load of checks to the very 181da177e4SLinus Torvalds * top level. 191da177e4SLinus Torvalds * Alan Cox : Move address structures to/from user 201da177e4SLinus Torvalds * mode above the protocol layers. 211da177e4SLinus Torvalds * Rob Janssen : Allow 0 length sends. 221da177e4SLinus Torvalds * Alan Cox : Asynchronous I/O support (cribbed from the 231da177e4SLinus Torvalds * tty drivers). 241da177e4SLinus Torvalds * Niibe Yutaka : Asynchronous I/O for writes (4.4BSD style) 251da177e4SLinus Torvalds * Jeff Uphoff : Made max number of sockets command-line 261da177e4SLinus Torvalds * configurable. 271da177e4SLinus Torvalds * Matti Aarnio : Made the number of sockets dynamic, 281da177e4SLinus Torvalds * to be allocated when needed, and mr. 291da177e4SLinus Torvalds * Uphoff's max is used as max to be 301da177e4SLinus Torvalds * allowed to allocate. 311da177e4SLinus Torvalds * Linus : Argh. removed all the socket allocation 321da177e4SLinus Torvalds * altogether: it's in the inode now. 331da177e4SLinus Torvalds * Alan Cox : Made sock_alloc()/sock_release() public 341da177e4SLinus Torvalds * for NetROM and future kernel nfsd type 351da177e4SLinus Torvalds * stuff. 361da177e4SLinus Torvalds * Alan Cox : sendmsg/recvmsg basics. 371da177e4SLinus Torvalds * Tom Dyas : Export net symbols. 381da177e4SLinus Torvalds * Marcin Dalecki : Fixed problems with CONFIG_NET="n". 391da177e4SLinus Torvalds * Alan Cox : Added thread locking to sys_* calls 401da177e4SLinus Torvalds * for sockets. May have errors at the 411da177e4SLinus Torvalds * moment. 421da177e4SLinus Torvalds * Kevin Buhr : Fixed the dumb errors in the above. 431da177e4SLinus Torvalds * Andi Kleen : Some small cleanups, optimizations, 441da177e4SLinus Torvalds * and fixed a copy_from_user() bug. 451da177e4SLinus Torvalds * Tigran Aivazian : sys_send(args) calls sys_sendto(args, NULL, 0) 461da177e4SLinus Torvalds * Tigran Aivazian : Made listen(2) backlog sanity checks 471da177e4SLinus Torvalds * protocol-independent 481da177e4SLinus Torvalds * 491da177e4SLinus Torvalds * This module is effectively the top level interface to the BSD socket 501da177e4SLinus Torvalds * paradigm. 511da177e4SLinus Torvalds * 521da177e4SLinus Torvalds * Based upon Swansea University Computer Society NET3.039 531da177e4SLinus Torvalds */ 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds #include <linux/mm.h> 561da177e4SLinus Torvalds #include <linux/socket.h> 571da177e4SLinus Torvalds #include <linux/file.h> 581da177e4SLinus Torvalds #include <linux/net.h> 591da177e4SLinus Torvalds #include <linux/interrupt.h> 60aaca0bdcSUlrich Drepper #include <linux/thread_info.h> 6155737fdaSStephen Hemminger #include <linux/rcupdate.h> 621da177e4SLinus Torvalds #include <linux/netdevice.h> 631da177e4SLinus Torvalds #include <linux/proc_fs.h> 641da177e4SLinus Torvalds #include <linux/seq_file.h> 654a3e2f71SArjan van de Ven #include <linux/mutex.h> 661da177e4SLinus Torvalds #include <linux/if_bridge.h> 6720380731SArnaldo Carvalho de Melo #include <linux/if_frad.h> 6820380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h> 69408eccceSDaniel Borkmann #include <linux/ptp_classify.h> 701da177e4SLinus Torvalds #include <linux/init.h> 711da177e4SLinus Torvalds #include <linux/poll.h> 721da177e4SLinus Torvalds #include <linux/cache.h> 731da177e4SLinus Torvalds #include <linux/module.h> 741da177e4SLinus Torvalds #include <linux/highmem.h> 751da177e4SLinus Torvalds #include <linux/mount.h> 76fba9be49SDavid Howells #include <linux/pseudo_fs.h> 771da177e4SLinus Torvalds #include <linux/security.h> 781da177e4SLinus Torvalds #include <linux/syscalls.h> 791da177e4SLinus Torvalds #include <linux/compat.h> 801da177e4SLinus Torvalds #include <linux/kmod.h> 813ec3b2fbSDavid Woodhouse #include <linux/audit.h> 82d86b5e0eSAdrian Bunk #include <linux/wireless.h> 831b8d7ae4SEric W. Biederman #include <linux/nsproxy.h> 841fd7317dSNick Black #include <linux/magic.h> 855a0e3ad6STejun Heo #include <linux/slab.h> 86600e1779SMasatake YAMATO #include <linux/xattr.h> 87c8e8cd57SJeremy Cline #include <linux/nospec.h> 888c3c447bSPaolo Abeni #include <linux/indirect_call_wrapper.h> 891da177e4SLinus Torvalds 907c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 911da177e4SLinus Torvalds #include <asm/unistd.h> 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds #include <net/compat.h> 9487de87d5SDavid S. Miller #include <net/wext.h> 95f8451725SHerbert Xu #include <net/cls_cgroup.h> 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds #include <net/sock.h> 981da177e4SLinus Torvalds #include <linux/netfilter.h> 991da177e4SLinus Torvalds 1006b96018bSArnd Bergmann #include <linux/if_tun.h> 1016b96018bSArnd Bergmann #include <linux/ipv6_route.h> 1026b96018bSArnd Bergmann #include <linux/route.h> 1036b96018bSArnd Bergmann #include <linux/sockios.h> 104076bb0c8SEliezer Tamir #include <net/busy_poll.h> 105f24b9be5SWillem de Bruijn #include <linux/errqueue.h> 10606021292SEliezer Tamir 107e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL 10864b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly; 10964b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly; 11006021292SEliezer Tamir #endif 1116b96018bSArnd Bergmann 1128ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to); 1138ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from); 1141da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma); 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file); 117a11e1d43SLinus Torvalds static __poll_t sock_poll(struct file *file, 118a11e1d43SLinus Torvalds struct poll_table_struct *wait); 11989bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 12089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 12189bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, 12289bbfc95SShaun Pereira unsigned int cmd, unsigned long arg); 12389bbfc95SShaun Pereira #endif 1241da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on); 1251da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page, 1261da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more); 1279c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 1289c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 1299c55e01cSJens Axboe unsigned int flags); 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds /* 1321da177e4SLinus Torvalds * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear 1331da177e4SLinus Torvalds * in the operation structures but are done directly via the socketcall() multiplexor. 1341da177e4SLinus Torvalds */ 1351da177e4SLinus Torvalds 136da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = { 1371da177e4SLinus Torvalds .owner = THIS_MODULE, 1381da177e4SLinus Torvalds .llseek = no_llseek, 1398ae5e030SAl Viro .read_iter = sock_read_iter, 1408ae5e030SAl Viro .write_iter = sock_write_iter, 1411da177e4SLinus Torvalds .poll = sock_poll, 1421da177e4SLinus Torvalds .unlocked_ioctl = sock_ioctl, 14389bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 14489bbfc95SShaun Pereira .compat_ioctl = compat_sock_ioctl, 14589bbfc95SShaun Pereira #endif 1461da177e4SLinus Torvalds .mmap = sock_mmap, 1471da177e4SLinus Torvalds .release = sock_close, 1481da177e4SLinus Torvalds .fasync = sock_fasync, 1495274f052SJens Axboe .sendpage = sock_sendpage, 1505274f052SJens Axboe .splice_write = generic_splice_sendpage, 1519c55e01cSJens Axboe .splice_read = sock_splice_read, 1521da177e4SLinus Torvalds }; 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds /* 1551da177e4SLinus Torvalds * The protocol list. Each protocol is registered in here. 1561da177e4SLinus Torvalds */ 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock); 159190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly; 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds /* 16289bddce5SStephen Hemminger * Support routines. 16389bddce5SStephen Hemminger * Move socket addresses back and forth across the kernel/user 1641da177e4SLinus Torvalds * divide and look after the messy bits. 1651da177e4SLinus Torvalds */ 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds /** 1681da177e4SLinus Torvalds * move_addr_to_kernel - copy a socket address into kernel space 1691da177e4SLinus Torvalds * @uaddr: Address in user space 1701da177e4SLinus Torvalds * @kaddr: Address in kernel space 1711da177e4SLinus Torvalds * @ulen: Length in user space 1721da177e4SLinus Torvalds * 1731da177e4SLinus Torvalds * The address is copied into kernel space. If the provided address is 1741da177e4SLinus Torvalds * too long an error code of -EINVAL is returned. If the copy gives 1751da177e4SLinus Torvalds * invalid addresses -EFAULT is returned. On a success 0 is returned. 1761da177e4SLinus Torvalds */ 1771da177e4SLinus Torvalds 17843db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr) 1791da177e4SLinus Torvalds { 180230b1839SYOSHIFUJI Hideaki if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) 1811da177e4SLinus Torvalds return -EINVAL; 1821da177e4SLinus Torvalds if (ulen == 0) 1831da177e4SLinus Torvalds return 0; 1841da177e4SLinus Torvalds if (copy_from_user(kaddr, uaddr, ulen)) 1851da177e4SLinus Torvalds return -EFAULT; 1863ec3b2fbSDavid Woodhouse return audit_sockaddr(ulen, kaddr); 1871da177e4SLinus Torvalds } 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds /** 1901da177e4SLinus Torvalds * move_addr_to_user - copy an address to user space 1911da177e4SLinus Torvalds * @kaddr: kernel space address 1921da177e4SLinus Torvalds * @klen: length of address in kernel 1931da177e4SLinus Torvalds * @uaddr: user space address 1941da177e4SLinus Torvalds * @ulen: pointer to user length field 1951da177e4SLinus Torvalds * 1961da177e4SLinus Torvalds * The value pointed to by ulen on entry is the buffer length available. 1971da177e4SLinus Torvalds * This is overwritten with the buffer space used. -EINVAL is returned 1981da177e4SLinus Torvalds * if an overlong buffer is specified or a negative buffer size. -EFAULT 1991da177e4SLinus Torvalds * is returned if either the buffer or the length field are not 2001da177e4SLinus Torvalds * accessible. 2011da177e4SLinus Torvalds * After copying the data up to the limit the user specifies, the true 2021da177e4SLinus Torvalds * length of the data is written over the length limit the user 2031da177e4SLinus Torvalds * specified. Zero is returned for a success. 2041da177e4SLinus Torvalds */ 2051da177e4SLinus Torvalds 20643db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, 20711165f14Sstephen hemminger void __user *uaddr, int __user *ulen) 2081da177e4SLinus Torvalds { 2091da177e4SLinus Torvalds int err; 2101da177e4SLinus Torvalds int len; 2111da177e4SLinus Torvalds 21268c6beb3SHannes Frederic Sowa BUG_ON(klen > sizeof(struct sockaddr_storage)); 21389bddce5SStephen Hemminger err = get_user(len, ulen); 21489bddce5SStephen Hemminger if (err) 2151da177e4SLinus Torvalds return err; 2161da177e4SLinus Torvalds if (len > klen) 2171da177e4SLinus Torvalds len = klen; 21868c6beb3SHannes Frederic Sowa if (len < 0) 2191da177e4SLinus Torvalds return -EINVAL; 22089bddce5SStephen Hemminger if (len) { 221d6fe3945SSteve Grubb if (audit_sockaddr(klen, kaddr)) 222d6fe3945SSteve Grubb return -ENOMEM; 2231da177e4SLinus Torvalds if (copy_to_user(uaddr, kaddr, len)) 2241da177e4SLinus Torvalds return -EFAULT; 2251da177e4SLinus Torvalds } 2261da177e4SLinus Torvalds /* 2271da177e4SLinus Torvalds * "fromlen shall refer to the value before truncation.." 2281da177e4SLinus Torvalds * 1003.1g 2291da177e4SLinus Torvalds */ 2301da177e4SLinus Torvalds return __put_user(klen, ulen); 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds 23308009a76SAlexey Dobriyan static struct kmem_cache *sock_inode_cachep __ro_after_init; 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb) 2361da177e4SLinus Torvalds { 2371da177e4SLinus Torvalds struct socket_alloc *ei; 23889bddce5SStephen Hemminger 239e94b1766SChristoph Lameter ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); 2401da177e4SLinus Torvalds if (!ei) 2411da177e4SLinus Torvalds return NULL; 242333f7909SAl Viro init_waitqueue_head(&ei->socket.wq.wait); 243333f7909SAl Viro ei->socket.wq.fasync_list = NULL; 244333f7909SAl Viro ei->socket.wq.flags = 0; 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds ei->socket.state = SS_UNCONNECTED; 2471da177e4SLinus Torvalds ei->socket.flags = 0; 2481da177e4SLinus Torvalds ei->socket.ops = NULL; 2491da177e4SLinus Torvalds ei->socket.sk = NULL; 2501da177e4SLinus Torvalds ei->socket.file = NULL; 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds return &ei->vfs_inode; 2531da177e4SLinus Torvalds } 2541da177e4SLinus Torvalds 2556d7855c5SAl Viro static void sock_free_inode(struct inode *inode) 2561da177e4SLinus Torvalds { 25743815482SEric Dumazet struct socket_alloc *ei; 25843815482SEric Dumazet 25943815482SEric Dumazet ei = container_of(inode, struct socket_alloc, vfs_inode); 26043815482SEric Dumazet kmem_cache_free(sock_inode_cachep, ei); 2611da177e4SLinus Torvalds } 2621da177e4SLinus Torvalds 26351cc5068SAlexey Dobriyan static void init_once(void *foo) 2641da177e4SLinus Torvalds { 2651da177e4SLinus Torvalds struct socket_alloc *ei = (struct socket_alloc *)foo; 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode); 2681da177e4SLinus Torvalds } 2691da177e4SLinus Torvalds 2701e911632Syuan linyu static void init_inodecache(void) 2711da177e4SLinus Torvalds { 2721da177e4SLinus Torvalds sock_inode_cachep = kmem_cache_create("sock_inode_cache", 2731da177e4SLinus Torvalds sizeof(struct socket_alloc), 27489bddce5SStephen Hemminger 0, 27589bddce5SStephen Hemminger (SLAB_HWCACHE_ALIGN | 27689bddce5SStephen Hemminger SLAB_RECLAIM_ACCOUNT | 2775d097056SVladimir Davydov SLAB_MEM_SPREAD | SLAB_ACCOUNT), 27820c2df83SPaul Mundt init_once); 2791e911632Syuan linyu BUG_ON(sock_inode_cachep == NULL); 2801da177e4SLinus Torvalds } 2811da177e4SLinus Torvalds 282b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = { 2831da177e4SLinus Torvalds .alloc_inode = sock_alloc_inode, 2846d7855c5SAl Viro .free_inode = sock_free_inode, 2851da177e4SLinus Torvalds .statfs = simple_statfs, 2861da177e4SLinus Torvalds }; 2871da177e4SLinus Torvalds 288c23fbb6bSEric Dumazet /* 289c23fbb6bSEric Dumazet * sockfs_dname() is called from d_path(). 290c23fbb6bSEric Dumazet */ 291c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) 292c23fbb6bSEric Dumazet { 293c23fbb6bSEric Dumazet return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", 294c5ef6035SDavid Howells d_inode(dentry)->i_ino); 295c23fbb6bSEric Dumazet } 296c23fbb6bSEric Dumazet 2973ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = { 298c23fbb6bSEric Dumazet .d_dname = sockfs_dname, 2991da177e4SLinus Torvalds }; 3001da177e4SLinus Torvalds 301bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler, 302bba0bd31SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 303bba0bd31SAndreas Gruenbacher const char *suffix, void *value, size_t size) 304bba0bd31SAndreas Gruenbacher { 305bba0bd31SAndreas Gruenbacher if (value) { 306bba0bd31SAndreas Gruenbacher if (dentry->d_name.len + 1 > size) 307bba0bd31SAndreas Gruenbacher return -ERANGE; 308bba0bd31SAndreas Gruenbacher memcpy(value, dentry->d_name.name, dentry->d_name.len + 1); 309bba0bd31SAndreas Gruenbacher } 310bba0bd31SAndreas Gruenbacher return dentry->d_name.len + 1; 311bba0bd31SAndreas Gruenbacher } 312bba0bd31SAndreas Gruenbacher 313bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname" 314bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX) 315bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1) 316bba0bd31SAndreas Gruenbacher 317bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = { 318bba0bd31SAndreas Gruenbacher .name = XATTR_NAME_SOCKPROTONAME, 319bba0bd31SAndreas Gruenbacher .get = sockfs_xattr_get, 320bba0bd31SAndreas Gruenbacher }; 321bba0bd31SAndreas Gruenbacher 3224a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler, 3234a590153SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 3244a590153SAndreas Gruenbacher const char *suffix, const void *value, 3254a590153SAndreas Gruenbacher size_t size, int flags) 3264a590153SAndreas Gruenbacher { 3274a590153SAndreas Gruenbacher /* Handled by LSM. */ 3284a590153SAndreas Gruenbacher return -EAGAIN; 3294a590153SAndreas Gruenbacher } 3304a590153SAndreas Gruenbacher 3314a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = { 3324a590153SAndreas Gruenbacher .prefix = XATTR_SECURITY_PREFIX, 3334a590153SAndreas Gruenbacher .set = sockfs_security_xattr_set, 3344a590153SAndreas Gruenbacher }; 3354a590153SAndreas Gruenbacher 336bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = { 337bba0bd31SAndreas Gruenbacher &sockfs_xattr_handler, 3384a590153SAndreas Gruenbacher &sockfs_security_xattr_handler, 339bba0bd31SAndreas Gruenbacher NULL 340bba0bd31SAndreas Gruenbacher }; 341bba0bd31SAndreas Gruenbacher 342fba9be49SDavid Howells static int sockfs_init_fs_context(struct fs_context *fc) 343c74a1cbbSAl Viro { 344fba9be49SDavid Howells struct pseudo_fs_context *ctx = init_pseudo(fc, SOCKFS_MAGIC); 345fba9be49SDavid Howells if (!ctx) 346fba9be49SDavid Howells return -ENOMEM; 347fba9be49SDavid Howells ctx->ops = &sockfs_ops; 348fba9be49SDavid Howells ctx->dops = &sockfs_dentry_operations; 349fba9be49SDavid Howells ctx->xattr = sockfs_xattr_handlers; 350fba9be49SDavid Howells return 0; 351c74a1cbbSAl Viro } 352c74a1cbbSAl Viro 353c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly; 354c74a1cbbSAl Viro 355c74a1cbbSAl Viro static struct file_system_type sock_fs_type = { 356c74a1cbbSAl Viro .name = "sockfs", 357fba9be49SDavid Howells .init_fs_context = sockfs_init_fs_context, 358c74a1cbbSAl Viro .kill_sb = kill_anon_super, 359c74a1cbbSAl Viro }; 360c74a1cbbSAl Viro 3611da177e4SLinus Torvalds /* 3621da177e4SLinus Torvalds * Obtains the first available file descriptor and sets it up for use. 3631da177e4SLinus Torvalds * 36439d8c1b6SDavid S. Miller * These functions create file structures and maps them to fd space 36539d8c1b6SDavid S. Miller * of the current process. On success it returns file descriptor 3661da177e4SLinus Torvalds * and file struct implicitly stored in sock->file. 3671da177e4SLinus Torvalds * Note that another thread may close file descriptor before we return 3681da177e4SLinus Torvalds * from this function. We use the fact that now we do not refer 3691da177e4SLinus Torvalds * to socket after mapping. If one day we will need it, this 3701da177e4SLinus Torvalds * function will increment ref. count on file by 1. 3711da177e4SLinus Torvalds * 3721da177e4SLinus Torvalds * In any case returned fd MAY BE not valid! 3731da177e4SLinus Torvalds * This race condition is unavoidable 3741da177e4SLinus Torvalds * with shared fd spaces, we cannot solve it inside kernel, 3751da177e4SLinus Torvalds * but we take care of internal coherence yet. 3761da177e4SLinus Torvalds */ 3771da177e4SLinus Torvalds 3788a3c245cSPedro Tammela /** 3798a3c245cSPedro Tammela * sock_alloc_file - Bind a &socket to a &file 3808a3c245cSPedro Tammela * @sock: socket 3818a3c245cSPedro Tammela * @flags: file status flags 3828a3c245cSPedro Tammela * @dname: protocol name 3838a3c245cSPedro Tammela * 3848a3c245cSPedro Tammela * Returns the &file bound with @sock, implicitly storing it 3858a3c245cSPedro Tammela * in sock->file. If dname is %NULL, sets to "". 3868a3c245cSPedro Tammela * On failure the return is a ERR pointer (see linux/err.h). 3878a3c245cSPedro Tammela * This function uses GFP_KERNEL internally. 3888a3c245cSPedro Tammela */ 3898a3c245cSPedro Tammela 390aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) 3911da177e4SLinus Torvalds { 3927cbe66b6SAl Viro struct file *file; 3931da177e4SLinus Torvalds 394d93aa9d8SAl Viro if (!dname) 395d93aa9d8SAl Viro dname = sock->sk ? sock->sk->sk_prot_creator->name : ""; 39639d8c1b6SDavid S. Miller 397d93aa9d8SAl Viro file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname, 398d93aa9d8SAl Viro O_RDWR | (flags & O_NONBLOCK), 399cc3808f8SAl Viro &socket_file_ops); 400b5ffe634SViresh Kumar if (IS_ERR(file)) { 4018e1611e2SAl Viro sock_release(sock); 40239b65252SAnatol Pomozov return file; 403cc3808f8SAl Viro } 4041da177e4SLinus Torvalds 4051da177e4SLinus Torvalds sock->file = file; 40607dc3f07SBenjamin LaHaise file->private_data = sock; 407d8e464ecSLinus Torvalds stream_open(SOCK_INODE(sock), file); 40828407630SAl Viro return file; 4091da177e4SLinus Torvalds } 41056b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file); 4111da177e4SLinus Torvalds 41256b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags) 41339d8c1b6SDavid S. Miller { 41439d8c1b6SDavid S. Miller struct file *newfile; 41528407630SAl Viro int fd = get_unused_fd_flags(flags); 416ce4bb04cSAl Viro if (unlikely(fd < 0)) { 417ce4bb04cSAl Viro sock_release(sock); 4181da177e4SLinus Torvalds return fd; 419ce4bb04cSAl Viro } 4201da177e4SLinus Torvalds 421aab174f0SLinus Torvalds newfile = sock_alloc_file(sock, flags, NULL); 4224546e44cSEnrico Weigelt if (!IS_ERR(newfile)) { 4231da177e4SLinus Torvalds fd_install(fd, newfile); 4241da177e4SLinus Torvalds return fd; 4251da177e4SLinus Torvalds } 42628407630SAl Viro 42728407630SAl Viro put_unused_fd(fd); 42828407630SAl Viro return PTR_ERR(newfile); 4291da177e4SLinus Torvalds } 4301da177e4SLinus Torvalds 4318a3c245cSPedro Tammela /** 4328a3c245cSPedro Tammela * sock_from_file - Return the &socket bounded to @file. 4338a3c245cSPedro Tammela * @file: file 4348a3c245cSPedro Tammela * @err: pointer to an error code return 4358a3c245cSPedro Tammela * 4368a3c245cSPedro Tammela * On failure returns %NULL and assigns -ENOTSOCK to @err. 4378a3c245cSPedro Tammela */ 4388a3c245cSPedro Tammela 439406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err) 4406cb153caSBenjamin LaHaise { 4416cb153caSBenjamin LaHaise if (file->f_op == &socket_file_ops) 4426cb153caSBenjamin LaHaise return file->private_data; /* set in sock_map_fd */ 4436cb153caSBenjamin LaHaise 4446cb153caSBenjamin LaHaise *err = -ENOTSOCK; 4456cb153caSBenjamin LaHaise return NULL; 4466cb153caSBenjamin LaHaise } 447406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file); 4486cb153caSBenjamin LaHaise 4491da177e4SLinus Torvalds /** 4501da177e4SLinus Torvalds * sockfd_lookup - Go from a file number to its socket slot 4511da177e4SLinus Torvalds * @fd: file handle 4521da177e4SLinus Torvalds * @err: pointer to an error code return 4531da177e4SLinus Torvalds * 4541da177e4SLinus Torvalds * The file handle passed in is locked and the socket it is bound 455241c4667SRosen, Rami * to is returned. If an error occurs the err pointer is overwritten 4561da177e4SLinus Torvalds * with a negative errno code and NULL is returned. The function checks 4571da177e4SLinus Torvalds * for both invalid handles and passing a handle which is not a socket. 4581da177e4SLinus Torvalds * 4591da177e4SLinus Torvalds * On a success the socket object pointer is returned. 4601da177e4SLinus Torvalds */ 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err) 4631da177e4SLinus Torvalds { 4641da177e4SLinus Torvalds struct file *file; 4651da177e4SLinus Torvalds struct socket *sock; 4661da177e4SLinus Torvalds 46789bddce5SStephen Hemminger file = fget(fd); 46889bddce5SStephen Hemminger if (!file) { 4691da177e4SLinus Torvalds *err = -EBADF; 4701da177e4SLinus Torvalds return NULL; 4711da177e4SLinus Torvalds } 47289bddce5SStephen Hemminger 4736cb153caSBenjamin LaHaise sock = sock_from_file(file, err); 4746cb153caSBenjamin LaHaise if (!sock) 4751da177e4SLinus Torvalds fput(file); 4766cb153caSBenjamin LaHaise return sock; 4771da177e4SLinus Torvalds } 478c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup); 4791da177e4SLinus Torvalds 4806cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) 4816cb153caSBenjamin LaHaise { 48200e188efSAl Viro struct fd f = fdget(fd); 4836cb153caSBenjamin LaHaise struct socket *sock; 4846cb153caSBenjamin LaHaise 4853672558cSHua Zhong *err = -EBADF; 48600e188efSAl Viro if (f.file) { 48700e188efSAl Viro sock = sock_from_file(f.file, err); 48800e188efSAl Viro if (likely(sock)) { 48900e188efSAl Viro *fput_needed = f.flags; 4901da177e4SLinus Torvalds return sock; 49100e188efSAl Viro } 49200e188efSAl Viro fdput(f); 4936cb153caSBenjamin LaHaise } 4946cb153caSBenjamin LaHaise return NULL; 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds 497600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, 498600e1779SMasatake YAMATO size_t size) 499600e1779SMasatake YAMATO { 500600e1779SMasatake YAMATO ssize_t len; 501600e1779SMasatake YAMATO ssize_t used = 0; 502600e1779SMasatake YAMATO 503c5ef6035SDavid Howells len = security_inode_listsecurity(d_inode(dentry), buffer, size); 504600e1779SMasatake YAMATO if (len < 0) 505600e1779SMasatake YAMATO return len; 506600e1779SMasatake YAMATO used += len; 507600e1779SMasatake YAMATO if (buffer) { 508600e1779SMasatake YAMATO if (size < used) 509600e1779SMasatake YAMATO return -ERANGE; 510600e1779SMasatake YAMATO buffer += len; 511600e1779SMasatake YAMATO } 512600e1779SMasatake YAMATO 513600e1779SMasatake YAMATO len = (XATTR_NAME_SOCKPROTONAME_LEN + 1); 514600e1779SMasatake YAMATO used += len; 515600e1779SMasatake YAMATO if (buffer) { 516600e1779SMasatake YAMATO if (size < used) 517600e1779SMasatake YAMATO return -ERANGE; 518600e1779SMasatake YAMATO memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len); 519600e1779SMasatake YAMATO buffer += len; 520600e1779SMasatake YAMATO } 521600e1779SMasatake YAMATO 522600e1779SMasatake YAMATO return used; 523600e1779SMasatake YAMATO } 524600e1779SMasatake YAMATO 525dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr) 52686741ec2SLorenzo Colitti { 52786741ec2SLorenzo Colitti int err = simple_setattr(dentry, iattr); 52886741ec2SLorenzo Colitti 529e1a3a60aSEric Biggers if (!err && (iattr->ia_valid & ATTR_UID)) { 53086741ec2SLorenzo Colitti struct socket *sock = SOCKET_I(d_inode(dentry)); 53186741ec2SLorenzo Colitti 5326d8c50dcSCong Wang if (sock->sk) 53386741ec2SLorenzo Colitti sock->sk->sk_uid = iattr->ia_uid; 5346d8c50dcSCong Wang else 5356d8c50dcSCong Wang err = -ENOENT; 53686741ec2SLorenzo Colitti } 53786741ec2SLorenzo Colitti 53886741ec2SLorenzo Colitti return err; 53986741ec2SLorenzo Colitti } 54086741ec2SLorenzo Colitti 541600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = { 542600e1779SMasatake YAMATO .listxattr = sockfs_listxattr, 54386741ec2SLorenzo Colitti .setattr = sockfs_setattr, 544600e1779SMasatake YAMATO }; 545600e1779SMasatake YAMATO 5461da177e4SLinus Torvalds /** 5471da177e4SLinus Torvalds * sock_alloc - allocate a socket 5481da177e4SLinus Torvalds * 5491da177e4SLinus Torvalds * Allocate a new inode and socket object. The two are bound together 5501da177e4SLinus Torvalds * and initialised. The socket is then returned. If we are out of inodes 5518a3c245cSPedro Tammela * NULL is returned. This functions uses GFP_KERNEL internally. 5521da177e4SLinus Torvalds */ 5531da177e4SLinus Torvalds 554f4a00aacSTom Herbert struct socket *sock_alloc(void) 5551da177e4SLinus Torvalds { 5561da177e4SLinus Torvalds struct inode *inode; 5571da177e4SLinus Torvalds struct socket *sock; 5581da177e4SLinus Torvalds 559a209dfc7SEric Dumazet inode = new_inode_pseudo(sock_mnt->mnt_sb); 5601da177e4SLinus Torvalds if (!inode) 5611da177e4SLinus Torvalds return NULL; 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds sock = SOCKET_I(inode); 5641da177e4SLinus Torvalds 56585fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 5661da177e4SLinus Torvalds inode->i_mode = S_IFSOCK | S_IRWXUGO; 5678192b0c4SDavid Howells inode->i_uid = current_fsuid(); 5688192b0c4SDavid Howells inode->i_gid = current_fsgid(); 569600e1779SMasatake YAMATO inode->i_op = &sockfs_inode_ops; 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds return sock; 5721da177e4SLinus Torvalds } 573f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc); 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds /** 5761da177e4SLinus Torvalds * sock_release - close a socket 5771da177e4SLinus Torvalds * @sock: socket to close 5781da177e4SLinus Torvalds * 5791da177e4SLinus Torvalds * The socket is released from the protocol stack if it has a release 5801da177e4SLinus Torvalds * callback, and the inode is then released if the socket is bound to 5811da177e4SLinus Torvalds * an inode not a file. 5821da177e4SLinus Torvalds */ 5831da177e4SLinus Torvalds 5846d8c50dcSCong Wang static void __sock_release(struct socket *sock, struct inode *inode) 5851da177e4SLinus Torvalds { 5861da177e4SLinus Torvalds if (sock->ops) { 5871da177e4SLinus Torvalds struct module *owner = sock->ops->owner; 5881da177e4SLinus Torvalds 5896d8c50dcSCong Wang if (inode) 5906d8c50dcSCong Wang inode_lock(inode); 5911da177e4SLinus Torvalds sock->ops->release(sock); 592ff7b11aaSEric Biggers sock->sk = NULL; 5936d8c50dcSCong Wang if (inode) 5946d8c50dcSCong Wang inode_unlock(inode); 5951da177e4SLinus Torvalds sock->ops = NULL; 5961da177e4SLinus Torvalds module_put(owner); 5971da177e4SLinus Torvalds } 5981da177e4SLinus Torvalds 599333f7909SAl Viro if (sock->wq.fasync_list) 6003410f22eSYang Yingliang pr_err("%s: fasync list not empty!\n", __func__); 6011da177e4SLinus Torvalds 6021da177e4SLinus Torvalds if (!sock->file) { 6031da177e4SLinus Torvalds iput(SOCK_INODE(sock)); 6041da177e4SLinus Torvalds return; 6051da177e4SLinus Torvalds } 6061da177e4SLinus Torvalds sock->file = NULL; 6071da177e4SLinus Torvalds } 6086d8c50dcSCong Wang 6096d8c50dcSCong Wang void sock_release(struct socket *sock) 6106d8c50dcSCong Wang { 6116d8c50dcSCong Wang __sock_release(sock, NULL); 6126d8c50dcSCong Wang } 613c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release); 6141da177e4SLinus Torvalds 615c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) 61620d49473SPatrick Ohly { 617140c55d4SEric Dumazet u8 flags = *tx_flags; 618140c55d4SEric Dumazet 619c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE) 620140c55d4SEric Dumazet flags |= SKBTX_HW_TSTAMP; 621140c55d4SEric Dumazet 622c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) 623140c55d4SEric Dumazet flags |= SKBTX_SW_TSTAMP; 624140c55d4SEric Dumazet 625c14ac945SSoheil Hassas Yeganeh if (tsflags & SOF_TIMESTAMPING_TX_SCHED) 626140c55d4SEric Dumazet flags |= SKBTX_SCHED_TSTAMP; 627140c55d4SEric Dumazet 628140c55d4SEric Dumazet *tx_flags = flags; 62920d49473SPatrick Ohly } 63067cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp); 63120d49473SPatrick Ohly 6328c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_sendmsg(struct socket *, struct msghdr *, 6338c3c447bSPaolo Abeni size_t)); 634a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_sendmsg(struct socket *, struct msghdr *, 635a648a592SPaolo Abeni size_t)); 636d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) 6371da177e4SLinus Torvalds { 638a648a592SPaolo Abeni int ret = INDIRECT_CALL_INET(sock->ops->sendmsg, inet6_sendmsg, 639a648a592SPaolo Abeni inet_sendmsg, sock, msg, 640a648a592SPaolo Abeni msg_data_left(msg)); 641d8725c86SAl Viro BUG_ON(ret == -EIOCBQUEUED); 642d8725c86SAl Viro return ret; 6431da177e4SLinus Torvalds } 6440cf00c6fSGu Zheng 64585806af0SRandy Dunlap /** 64685806af0SRandy Dunlap * sock_sendmsg - send a message through @sock 64785806af0SRandy Dunlap * @sock: socket 64885806af0SRandy Dunlap * @msg: message to send 64985806af0SRandy Dunlap * 65085806af0SRandy Dunlap * Sends @msg through @sock, passing through LSM. 65185806af0SRandy Dunlap * Returns the number of bytes sent, or an error code. 65285806af0SRandy Dunlap */ 653d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg) 6540cf00c6fSGu Zheng { 655d8725c86SAl Viro int err = security_socket_sendmsg(sock, msg, 65601e97e65SAl Viro msg_data_left(msg)); 6571b784140SYing Xue 658d8725c86SAl Viro return err ?: sock_sendmsg_nosec(sock, msg); 6590cf00c6fSGu Zheng } 660c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg); 6611da177e4SLinus Torvalds 6628a3c245cSPedro Tammela /** 6638a3c245cSPedro Tammela * kernel_sendmsg - send a message through @sock (kernel-space) 6648a3c245cSPedro Tammela * @sock: socket 6658a3c245cSPedro Tammela * @msg: message header 6668a3c245cSPedro Tammela * @vec: kernel vec 6678a3c245cSPedro Tammela * @num: vec array length 6688a3c245cSPedro Tammela * @size: total message data size 6698a3c245cSPedro Tammela * 6708a3c245cSPedro Tammela * Builds the message data with @vec and sends it through @sock. 6718a3c245cSPedro Tammela * Returns the number of bytes sent, or an error code. 6728a3c245cSPedro Tammela */ 6738a3c245cSPedro Tammela 6741da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg, 6751da177e4SLinus Torvalds struct kvec *vec, size_t num, size_t size) 6761da177e4SLinus Torvalds { 677aa563d7bSDavid Howells iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size); 678d8725c86SAl Viro return sock_sendmsg(sock, msg); 6791da177e4SLinus Torvalds } 680c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg); 6811da177e4SLinus Torvalds 6828a3c245cSPedro Tammela /** 6838a3c245cSPedro Tammela * kernel_sendmsg_locked - send a message through @sock (kernel-space) 6848a3c245cSPedro Tammela * @sk: sock 6858a3c245cSPedro Tammela * @msg: message header 6868a3c245cSPedro Tammela * @vec: output s/g array 6878a3c245cSPedro Tammela * @num: output s/g array length 6888a3c245cSPedro Tammela * @size: total message data size 6898a3c245cSPedro Tammela * 6908a3c245cSPedro Tammela * Builds the message data with @vec and sends it through @sock. 6918a3c245cSPedro Tammela * Returns the number of bytes sent, or an error code. 6928a3c245cSPedro Tammela * Caller must hold @sk. 6938a3c245cSPedro Tammela */ 6948a3c245cSPedro Tammela 695306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg, 696306b13ebSTom Herbert struct kvec *vec, size_t num, size_t size) 697306b13ebSTom Herbert { 698306b13ebSTom Herbert struct socket *sock = sk->sk_socket; 699306b13ebSTom Herbert 700306b13ebSTom Herbert if (!sock->ops->sendmsg_locked) 701db5980d8SJohn Fastabend return sock_no_sendmsg_locked(sk, msg, size); 702306b13ebSTom Herbert 703aa563d7bSDavid Howells iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size); 704306b13ebSTom Herbert 705306b13ebSTom Herbert return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg)); 706306b13ebSTom Herbert } 707306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked); 708306b13ebSTom Herbert 7098605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb) 7108605330aSSoheil Hassas Yeganeh { 7118605330aSSoheil Hassas Yeganeh /* pkt_type of skbs enqueued on the error queue are set to 7128605330aSSoheil Hassas Yeganeh * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do 7138605330aSSoheil Hassas Yeganeh * in recvmsg, since skbs received on a local socket will never 7148605330aSSoheil Hassas Yeganeh * have a pkt_type of PACKET_OUTGOING. 7158605330aSSoheil Hassas Yeganeh */ 7168605330aSSoheil Hassas Yeganeh return skb->pkt_type == PACKET_OUTGOING; 7178605330aSSoheil Hassas Yeganeh } 7188605330aSSoheil Hassas Yeganeh 719b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently. 720b50a5c70SMiroslav Lichvar * As the two skb clones share the hardware timestamp, which may be updated 721b50a5c70SMiroslav Lichvar * before the software timestamp is received, a hardware TX timestamp may be 722b50a5c70SMiroslav Lichvar * returned only if there is no software TX timestamp. Ignore false software 723b50a5c70SMiroslav Lichvar * timestamps, which may be made in the __sock_recv_timestamp() call when the 7247f1bc6e9SDeepa Dinamani * option SO_TIMESTAMP_OLD(NS) is enabled on the socket, even when the skb has a 725b50a5c70SMiroslav Lichvar * hardware timestamp. 726b50a5c70SMiroslav Lichvar */ 727b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp) 728b50a5c70SMiroslav Lichvar { 729b50a5c70SMiroslav Lichvar return skb->tstamp && !false_tstamp && skb_is_err_queue(skb); 730b50a5c70SMiroslav Lichvar } 731b50a5c70SMiroslav Lichvar 732aad9c8c4SMiroslav Lichvar static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb) 733aad9c8c4SMiroslav Lichvar { 734aad9c8c4SMiroslav Lichvar struct scm_ts_pktinfo ts_pktinfo; 735aad9c8c4SMiroslav Lichvar struct net_device *orig_dev; 736aad9c8c4SMiroslav Lichvar 737aad9c8c4SMiroslav Lichvar if (!skb_mac_header_was_set(skb)) 738aad9c8c4SMiroslav Lichvar return; 739aad9c8c4SMiroslav Lichvar 740aad9c8c4SMiroslav Lichvar memset(&ts_pktinfo, 0, sizeof(ts_pktinfo)); 741aad9c8c4SMiroslav Lichvar 742aad9c8c4SMiroslav Lichvar rcu_read_lock(); 743aad9c8c4SMiroslav Lichvar orig_dev = dev_get_by_napi_id(skb_napi_id(skb)); 744aad9c8c4SMiroslav Lichvar if (orig_dev) 745aad9c8c4SMiroslav Lichvar ts_pktinfo.if_index = orig_dev->ifindex; 746aad9c8c4SMiroslav Lichvar rcu_read_unlock(); 747aad9c8c4SMiroslav Lichvar 748aad9c8c4SMiroslav Lichvar ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb); 749aad9c8c4SMiroslav Lichvar put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO, 750aad9c8c4SMiroslav Lichvar sizeof(ts_pktinfo), &ts_pktinfo); 751aad9c8c4SMiroslav Lichvar } 752aad9c8c4SMiroslav Lichvar 75392f37fd2SEric Dumazet /* 75492f37fd2SEric Dumazet * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) 75592f37fd2SEric Dumazet */ 75692f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 75792f37fd2SEric Dumazet struct sk_buff *skb) 75892f37fd2SEric Dumazet { 75920d49473SPatrick Ohly int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 760887feae3SDeepa Dinamani int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW); 7619718475eSDeepa Dinamani struct scm_timestamping_internal tss; 7629718475eSDeepa Dinamani 763b50a5c70SMiroslav Lichvar int empty = 1, false_tstamp = 0; 76420d49473SPatrick Ohly struct skb_shared_hwtstamps *shhwtstamps = 76520d49473SPatrick Ohly skb_hwtstamps(skb); 76692f37fd2SEric Dumazet 76720d49473SPatrick Ohly /* Race occurred between timestamp enabling and packet 76820d49473SPatrick Ohly receiving. Fill in the current time for now. */ 769b50a5c70SMiroslav Lichvar if (need_software_tstamp && skb->tstamp == 0) { 77020d49473SPatrick Ohly __net_timestamp(skb); 771b50a5c70SMiroslav Lichvar false_tstamp = 1; 772b50a5c70SMiroslav Lichvar } 77320d49473SPatrick Ohly 77420d49473SPatrick Ohly if (need_software_tstamp) { 77592f37fd2SEric Dumazet if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { 776887feae3SDeepa Dinamani if (new_tstamp) { 777887feae3SDeepa Dinamani struct __kernel_sock_timeval tv; 778887feae3SDeepa Dinamani 779887feae3SDeepa Dinamani skb_get_new_timestamp(skb, &tv); 780887feae3SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW, 781887feae3SDeepa Dinamani sizeof(tv), &tv); 782887feae3SDeepa Dinamani } else { 78313c6ee2aSDeepa Dinamani struct __kernel_old_timeval tv; 784887feae3SDeepa Dinamani 78520d49473SPatrick Ohly skb_get_timestamp(skb, &tv); 7867f1bc6e9SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD, 78720d49473SPatrick Ohly sizeof(tv), &tv); 788887feae3SDeepa Dinamani } 789887feae3SDeepa Dinamani } else { 790887feae3SDeepa Dinamani if (new_tstamp) { 791887feae3SDeepa Dinamani struct __kernel_timespec ts; 792887feae3SDeepa Dinamani 793887feae3SDeepa Dinamani skb_get_new_timestampns(skb, &ts); 794887feae3SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW, 795887feae3SDeepa Dinamani sizeof(ts), &ts); 79692f37fd2SEric Dumazet } else { 797f24b9be5SWillem de Bruijn struct timespec ts; 798887feae3SDeepa Dinamani 799f24b9be5SWillem de Bruijn skb_get_timestampns(skb, &ts); 8007f1bc6e9SDeepa Dinamani put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD, 801f24b9be5SWillem de Bruijn sizeof(ts), &ts); 80292f37fd2SEric Dumazet } 80392f37fd2SEric Dumazet } 804887feae3SDeepa Dinamani } 80592f37fd2SEric Dumazet 806f24b9be5SWillem de Bruijn memset(&tss, 0, sizeof(tss)); 807c199105dSWillem de Bruijn if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && 8089718475eSDeepa Dinamani ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0)) 80920d49473SPatrick Ohly empty = 0; 8104d276eb6SWillem de Bruijn if (shhwtstamps && 811b9f40e21SWillem de Bruijn (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && 812b50a5c70SMiroslav Lichvar !skb_is_swtx_tstamp(skb, false_tstamp) && 8139718475eSDeepa Dinamani ktime_to_timespec64_cond(shhwtstamps->hwtstamp, tss.ts + 2)) { 81420d49473SPatrick Ohly empty = 0; 815aad9c8c4SMiroslav Lichvar if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) && 816aad9c8c4SMiroslav Lichvar !skb_is_err_queue(skb)) 817aad9c8c4SMiroslav Lichvar put_ts_pktinfo(msg, skb); 818aad9c8c4SMiroslav Lichvar } 8191c885808SFrancis Yan if (!empty) { 8209718475eSDeepa Dinamani if (sock_flag(sk, SOCK_TSTAMP_NEW)) 8219718475eSDeepa Dinamani put_cmsg_scm_timestamping64(msg, &tss); 8229718475eSDeepa Dinamani else 8239718475eSDeepa Dinamani put_cmsg_scm_timestamping(msg, &tss); 8241c885808SFrancis Yan 8258605330aSSoheil Hassas Yeganeh if (skb_is_err_queue(skb) && skb->len && 8264ef1b286SSoheil Hassas Yeganeh SKB_EXT_ERR(skb)->opt_stats) 8271c885808SFrancis Yan put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, 8281c885808SFrancis Yan skb->len, skb->data); 8291c885808SFrancis Yan } 83020d49473SPatrick Ohly } 8317c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 8327c81fd8bSArnaldo Carvalho de Melo 8336e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, 8346e3e939fSJohannes Berg struct sk_buff *skb) 8356e3e939fSJohannes Berg { 8366e3e939fSJohannes Berg int ack; 8376e3e939fSJohannes Berg 8386e3e939fSJohannes Berg if (!sock_flag(sk, SOCK_WIFI_STATUS)) 8396e3e939fSJohannes Berg return; 8406e3e939fSJohannes Berg if (!skb->wifi_acked_valid) 8416e3e939fSJohannes Berg return; 8426e3e939fSJohannes Berg 8436e3e939fSJohannes Berg ack = skb->wifi_acked; 8446e3e939fSJohannes Berg 8456e3e939fSJohannes Berg put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack); 8466e3e939fSJohannes Berg } 8476e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status); 8486e3e939fSJohannes Berg 84911165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, 85011165f14Sstephen hemminger struct sk_buff *skb) 8513b885787SNeil Horman { 852744d5a3eSEyal Birger if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount) 8533b885787SNeil Horman put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, 854744d5a3eSEyal Birger sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount); 8553b885787SNeil Horman } 8563b885787SNeil Horman 857767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 8583b885787SNeil Horman struct sk_buff *skb) 8593b885787SNeil Horman { 8603b885787SNeil Horman sock_recv_timestamp(msg, sk, skb); 8613b885787SNeil Horman sock_recv_drops(msg, sk, skb); 8623b885787SNeil Horman } 863767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); 8643b885787SNeil Horman 8658c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_recvmsg(struct socket *, struct msghdr *, 8668c3c447bSPaolo Abeni size_t, int)); 867a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_recvmsg(struct socket *, struct msghdr *, 868a648a592SPaolo Abeni size_t, int)); 8691b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, 8701b784140SYing Xue int flags) 871a2e27255SArnaldo Carvalho de Melo { 872a648a592SPaolo Abeni return INDIRECT_CALL_INET(sock->ops->recvmsg, inet6_recvmsg, 873a648a592SPaolo Abeni inet_recvmsg, sock, msg, msg_data_left(msg), 874a648a592SPaolo Abeni flags); 8752da62906SAl Viro } 876a2e27255SArnaldo Carvalho de Melo 87785806af0SRandy Dunlap /** 87885806af0SRandy Dunlap * sock_recvmsg - receive a message from @sock 87985806af0SRandy Dunlap * @sock: socket 88085806af0SRandy Dunlap * @msg: message to receive 88185806af0SRandy Dunlap * @flags: message flags 88285806af0SRandy Dunlap * 88385806af0SRandy Dunlap * Receives @msg from @sock, passing through LSM. Returns the total number 88485806af0SRandy Dunlap * of bytes received, or an error. 88585806af0SRandy Dunlap */ 8862da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags) 8872da62906SAl Viro { 8882da62906SAl Viro int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags); 8892da62906SAl Viro 8902da62906SAl Viro return err ?: sock_recvmsg_nosec(sock, msg, flags); 8911da177e4SLinus Torvalds } 892c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg); 8931da177e4SLinus Torvalds 894c1249c0aSMartin Lucina /** 895c1249c0aSMartin Lucina * kernel_recvmsg - Receive a message from a socket (kernel space) 896c1249c0aSMartin Lucina * @sock: The socket to receive the message from 897c1249c0aSMartin Lucina * @msg: Received message 898c1249c0aSMartin Lucina * @vec: Input s/g array for message data 899c1249c0aSMartin Lucina * @num: Size of input s/g array 900c1249c0aSMartin Lucina * @size: Number of bytes to read 901c1249c0aSMartin Lucina * @flags: Message flags (MSG_DONTWAIT, etc...) 902c1249c0aSMartin Lucina * 903c1249c0aSMartin Lucina * On return the msg structure contains the scatter/gather array passed in the 904c1249c0aSMartin Lucina * vec argument. The array is modified so that it consists of the unfilled 905c1249c0aSMartin Lucina * portion of the original array. 906c1249c0aSMartin Lucina * 907c1249c0aSMartin Lucina * The returned value is the total number of bytes received, or an error. 908c1249c0aSMartin Lucina */ 9098a3c245cSPedro Tammela 9101da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg, 91189bddce5SStephen Hemminger struct kvec *vec, size_t num, size_t size, int flags) 9121da177e4SLinus Torvalds { 9131da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 9141da177e4SLinus Torvalds int result; 9151da177e4SLinus Torvalds 916aa563d7bSDavid Howells iov_iter_kvec(&msg->msg_iter, READ, vec, num, size); 9171da177e4SLinus Torvalds set_fs(KERNEL_DS); 9182da62906SAl Viro result = sock_recvmsg(sock, msg, flags); 9191da177e4SLinus Torvalds set_fs(oldfs); 9201da177e4SLinus Torvalds return result; 9211da177e4SLinus Torvalds } 922c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg); 9231da177e4SLinus Torvalds 92420380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page, 9251da177e4SLinus Torvalds int offset, size_t size, loff_t *ppos, int more) 9261da177e4SLinus Torvalds { 9271da177e4SLinus Torvalds struct socket *sock; 9281da177e4SLinus Torvalds int flags; 9291da177e4SLinus Torvalds 930b69aee04SEric Dumazet sock = file->private_data; 9311da177e4SLinus Torvalds 93235f9c09fSEric Dumazet flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; 93335f9c09fSEric Dumazet /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */ 93435f9c09fSEric Dumazet flags |= more; 9351da177e4SLinus Torvalds 936e6949583SLinus Torvalds return kernel_sendpage(sock, page, offset, size, flags); 9371da177e4SLinus Torvalds } 9381da177e4SLinus Torvalds 9399c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos, 9409c55e01cSJens Axboe struct pipe_inode_info *pipe, size_t len, 9419c55e01cSJens Axboe unsigned int flags) 9429c55e01cSJens Axboe { 9439c55e01cSJens Axboe struct socket *sock = file->private_data; 9449c55e01cSJens Axboe 945997b37daSRémi Denis-Courmont if (unlikely(!sock->ops->splice_read)) 94695506588SSlavomir Kaslev return generic_file_splice_read(file, ppos, pipe, len, flags); 947997b37daSRémi Denis-Courmont 9489c55e01cSJens Axboe return sock->ops->splice_read(sock, ppos, pipe, len, flags); 9499c55e01cSJens Axboe } 9509c55e01cSJens Axboe 9518ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to) 952ce1d4d3eSChristoph Hellwig { 9536d652330SAl Viro struct file *file = iocb->ki_filp; 9546d652330SAl Viro struct socket *sock = file->private_data; 9550345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *to, 9560345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 9578ae5e030SAl Viro ssize_t res; 958ce1d4d3eSChristoph Hellwig 9598ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 9608ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 9618ae5e030SAl Viro 9628ae5e030SAl Viro if (iocb->ki_pos != 0) 963ce1d4d3eSChristoph Hellwig return -ESPIPE; 964027445c3SBadari Pulavarty 96566ee59afSChristoph Hellwig if (!iov_iter_count(to)) /* Match SYS5 behaviour */ 966ce1d4d3eSChristoph Hellwig return 0; 967ce1d4d3eSChristoph Hellwig 9682da62906SAl Viro res = sock_recvmsg(sock, &msg, msg.msg_flags); 9698ae5e030SAl Viro *to = msg.msg_iter; 9708ae5e030SAl Viro return res; 971ce1d4d3eSChristoph Hellwig } 972ce1d4d3eSChristoph Hellwig 9738ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) 9741da177e4SLinus Torvalds { 9756d652330SAl Viro struct file *file = iocb->ki_filp; 9766d652330SAl Viro struct socket *sock = file->private_data; 9770345f931Stadeusz.struk@intel.com struct msghdr msg = {.msg_iter = *from, 9780345f931Stadeusz.struk@intel.com .msg_iocb = iocb}; 9798ae5e030SAl Viro ssize_t res; 9801da177e4SLinus Torvalds 9818ae5e030SAl Viro if (iocb->ki_pos != 0) 982ce1d4d3eSChristoph Hellwig return -ESPIPE; 983027445c3SBadari Pulavarty 9848ae5e030SAl Viro if (file->f_flags & O_NONBLOCK) 9858ae5e030SAl Viro msg.msg_flags = MSG_DONTWAIT; 9868ae5e030SAl Viro 9876d652330SAl Viro if (sock->type == SOCK_SEQPACKET) 9886d652330SAl Viro msg.msg_flags |= MSG_EOR; 9896d652330SAl Viro 990d8725c86SAl Viro res = sock_sendmsg(sock, &msg); 9918ae5e030SAl Viro *from = msg.msg_iter; 9928ae5e030SAl Viro return res; 9931da177e4SLinus Torvalds } 9941da177e4SLinus Torvalds 9951da177e4SLinus Torvalds /* 9961da177e4SLinus Torvalds * Atomic setting of ioctl hooks to avoid race 9971da177e4SLinus Torvalds * with module unload. 9981da177e4SLinus Torvalds */ 9991da177e4SLinus Torvalds 10004a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex); 1001c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg); 10021da177e4SLinus Torvalds 1003881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *)) 10041da177e4SLinus Torvalds { 10054a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 10061da177e4SLinus Torvalds br_ioctl_hook = hook; 10074a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 10081da177e4SLinus Torvalds } 10091da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set); 10101da177e4SLinus Torvalds 10114a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex); 1012881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg); 10131da177e4SLinus Torvalds 1014881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *)) 10151da177e4SLinus Torvalds { 10164a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 10171da177e4SLinus Torvalds vlan_ioctl_hook = hook; 10184a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 10191da177e4SLinus Torvalds } 10201da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set); 10211da177e4SLinus Torvalds 10224a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex); 10231da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *); 10241da177e4SLinus Torvalds 10251da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) 10261da177e4SLinus Torvalds { 10274a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 10281da177e4SLinus Torvalds dlci_ioctl_hook = hook; 10294a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 10301da177e4SLinus Torvalds } 10311da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set); 10321da177e4SLinus Torvalds 10336b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock, 103463ff03abSJohannes Berg unsigned int cmd, unsigned long arg) 10356b96018bSArnd Bergmann { 10366b96018bSArnd Bergmann int err; 10376b96018bSArnd Bergmann void __user *argp = (void __user *)arg; 10386b96018bSArnd Bergmann 10396b96018bSArnd Bergmann err = sock->ops->ioctl(sock, cmd, arg); 10406b96018bSArnd Bergmann 10416b96018bSArnd Bergmann /* 10426b96018bSArnd Bergmann * If this ioctl is unknown try to hand it down 10436b96018bSArnd Bergmann * to the NIC driver. 10446b96018bSArnd Bergmann */ 104536fd633eSAl Viro if (err != -ENOIOCTLCMD) 10466b96018bSArnd Bergmann return err; 10476b96018bSArnd Bergmann 104836fd633eSAl Viro if (cmd == SIOCGIFCONF) { 104936fd633eSAl Viro struct ifconf ifc; 105036fd633eSAl Viro if (copy_from_user(&ifc, argp, sizeof(struct ifconf))) 105136fd633eSAl Viro return -EFAULT; 105236fd633eSAl Viro rtnl_lock(); 105336fd633eSAl Viro err = dev_ifconf(net, &ifc, sizeof(struct ifreq)); 105436fd633eSAl Viro rtnl_unlock(); 105536fd633eSAl Viro if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf))) 105636fd633eSAl Viro err = -EFAULT; 105744c02a2cSAl Viro } else { 105844c02a2cSAl Viro struct ifreq ifr; 105944c02a2cSAl Viro bool need_copyout; 106063ff03abSJohannes Berg if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) 106144c02a2cSAl Viro return -EFAULT; 106244c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, &need_copyout); 106344c02a2cSAl Viro if (!err && need_copyout) 106463ff03abSJohannes Berg if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) 106544c02a2cSAl Viro return -EFAULT; 106636fd633eSAl Viro } 10676b96018bSArnd Bergmann return err; 10686b96018bSArnd Bergmann } 10696b96018bSArnd Bergmann 10701da177e4SLinus Torvalds /* 10711da177e4SLinus Torvalds * With an ioctl, arg may well be a user mode pointer, but we don't know 10721da177e4SLinus Torvalds * what to do with it - that's up to the protocol still. 10731da177e4SLinus Torvalds */ 10741da177e4SLinus Torvalds 10758a3c245cSPedro Tammela /** 10768a3c245cSPedro Tammela * get_net_ns - increment the refcount of the network namespace 10778a3c245cSPedro Tammela * @ns: common namespace (net) 10788a3c245cSPedro Tammela * 10798a3c245cSPedro Tammela * Returns the net's common namespace. 10808a3c245cSPedro Tammela */ 10818a3c245cSPedro Tammela 1082d8d211a2SKirill Tkhai struct ns_common *get_net_ns(struct ns_common *ns) 1083c62cce2cSAndrey Vagin { 1084c62cce2cSAndrey Vagin return &get_net(container_of(ns, struct net, ns))->ns; 1085c62cce2cSAndrey Vagin } 1086d8d211a2SKirill Tkhai EXPORT_SYMBOL_GPL(get_net_ns); 1087c62cce2cSAndrey Vagin 10881da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) 10891da177e4SLinus Torvalds { 10901da177e4SLinus Torvalds struct socket *sock; 1091881d966bSEric W. Biederman struct sock *sk; 10921da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 10931da177e4SLinus Torvalds int pid, err; 1094881d966bSEric W. Biederman struct net *net; 10951da177e4SLinus Torvalds 1096b69aee04SEric Dumazet sock = file->private_data; 1097881d966bSEric W. Biederman sk = sock->sk; 10983b1e0a65SYOSHIFUJI Hideaki net = sock_net(sk); 109944c02a2cSAl Viro if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) { 110044c02a2cSAl Viro struct ifreq ifr; 110144c02a2cSAl Viro bool need_copyout; 110244c02a2cSAl Viro if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) 110344c02a2cSAl Viro return -EFAULT; 110444c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, &need_copyout); 110544c02a2cSAl Viro if (!err && need_copyout) 110644c02a2cSAl Viro if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) 110744c02a2cSAl Viro return -EFAULT; 11081da177e4SLinus Torvalds } else 11093d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE 11101da177e4SLinus Torvalds if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { 1111b1b0c245SAl Viro err = wext_handle_ioctl(net, cmd, argp); 11121da177e4SLinus Torvalds } else 11133d23e349SJohannes Berg #endif 11141da177e4SLinus Torvalds switch (cmd) { 11151da177e4SLinus Torvalds case FIOSETOWN: 11161da177e4SLinus Torvalds case SIOCSPGRP: 11171da177e4SLinus Torvalds err = -EFAULT; 11181da177e4SLinus Torvalds if (get_user(pid, (int __user *)argp)) 11191da177e4SLinus Torvalds break; 1120393cc3f5SJiri Slaby err = f_setown(sock->file, pid, 1); 11211da177e4SLinus Torvalds break; 11221da177e4SLinus Torvalds case FIOGETOWN: 11231da177e4SLinus Torvalds case SIOCGPGRP: 1124609d7fa9SEric W. Biederman err = put_user(f_getown(sock->file), 112589bddce5SStephen Hemminger (int __user *)argp); 11261da177e4SLinus Torvalds break; 11271da177e4SLinus Torvalds case SIOCGIFBR: 11281da177e4SLinus Torvalds case SIOCSIFBR: 11291da177e4SLinus Torvalds case SIOCBRADDBR: 11301da177e4SLinus Torvalds case SIOCBRDELBR: 11311da177e4SLinus Torvalds err = -ENOPKG; 11321da177e4SLinus Torvalds if (!br_ioctl_hook) 11331da177e4SLinus Torvalds request_module("bridge"); 11341da177e4SLinus Torvalds 11354a3e2f71SArjan van de Ven mutex_lock(&br_ioctl_mutex); 11361da177e4SLinus Torvalds if (br_ioctl_hook) 1137881d966bSEric W. Biederman err = br_ioctl_hook(net, cmd, argp); 11384a3e2f71SArjan van de Ven mutex_unlock(&br_ioctl_mutex); 11391da177e4SLinus Torvalds break; 11401da177e4SLinus Torvalds case SIOCGIFVLAN: 11411da177e4SLinus Torvalds case SIOCSIFVLAN: 11421da177e4SLinus Torvalds err = -ENOPKG; 11431da177e4SLinus Torvalds if (!vlan_ioctl_hook) 11441da177e4SLinus Torvalds request_module("8021q"); 11451da177e4SLinus Torvalds 11464a3e2f71SArjan van de Ven mutex_lock(&vlan_ioctl_mutex); 11471da177e4SLinus Torvalds if (vlan_ioctl_hook) 1148881d966bSEric W. Biederman err = vlan_ioctl_hook(net, argp); 11494a3e2f71SArjan van de Ven mutex_unlock(&vlan_ioctl_mutex); 11501da177e4SLinus Torvalds break; 11511da177e4SLinus Torvalds case SIOCADDDLCI: 11521da177e4SLinus Torvalds case SIOCDELDLCI: 11531da177e4SLinus Torvalds err = -ENOPKG; 11541da177e4SLinus Torvalds if (!dlci_ioctl_hook) 11551da177e4SLinus Torvalds request_module("dlci"); 11561da177e4SLinus Torvalds 11574a3e2f71SArjan van de Ven mutex_lock(&dlci_ioctl_mutex); 11587512cbf6SPavel Emelyanov if (dlci_ioctl_hook) 11591da177e4SLinus Torvalds err = dlci_ioctl_hook(cmd, argp); 11604a3e2f71SArjan van de Ven mutex_unlock(&dlci_ioctl_mutex); 11611da177e4SLinus Torvalds break; 1162c62cce2cSAndrey Vagin case SIOCGSKNS: 1163c62cce2cSAndrey Vagin err = -EPERM; 1164c62cce2cSAndrey Vagin if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 1165c62cce2cSAndrey Vagin break; 1166c62cce2cSAndrey Vagin 1167c62cce2cSAndrey Vagin err = open_related_ns(&net->ns, get_net_ns); 1168c62cce2cSAndrey Vagin break; 11690768e170SArnd Bergmann case SIOCGSTAMP_OLD: 11700768e170SArnd Bergmann case SIOCGSTAMPNS_OLD: 1171c7cbdbf2SArnd Bergmann if (!sock->ops->gettstamp) { 1172c7cbdbf2SArnd Bergmann err = -ENOIOCTLCMD; 1173c7cbdbf2SArnd Bergmann break; 1174c7cbdbf2SArnd Bergmann } 1175c7cbdbf2SArnd Bergmann err = sock->ops->gettstamp(sock, argp, 11760768e170SArnd Bergmann cmd == SIOCGSTAMP_OLD, 11770768e170SArnd Bergmann !IS_ENABLED(CONFIG_64BIT)); 117860747828SGustavo A. R. Silva break; 11790768e170SArnd Bergmann case SIOCGSTAMP_NEW: 11800768e170SArnd Bergmann case SIOCGSTAMPNS_NEW: 11810768e170SArnd Bergmann if (!sock->ops->gettstamp) { 11820768e170SArnd Bergmann err = -ENOIOCTLCMD; 11830768e170SArnd Bergmann break; 11840768e170SArnd Bergmann } 11850768e170SArnd Bergmann err = sock->ops->gettstamp(sock, argp, 11860768e170SArnd Bergmann cmd == SIOCGSTAMP_NEW, 11870768e170SArnd Bergmann false); 1188c7cbdbf2SArnd Bergmann break; 11891da177e4SLinus Torvalds default: 119063ff03abSJohannes Berg err = sock_do_ioctl(net, sock, cmd, arg); 11911da177e4SLinus Torvalds break; 11921da177e4SLinus Torvalds } 11931da177e4SLinus Torvalds return err; 11941da177e4SLinus Torvalds } 11951da177e4SLinus Torvalds 11968a3c245cSPedro Tammela /** 11978a3c245cSPedro Tammela * sock_create_lite - creates a socket 11988a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...) 11998a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...) 12008a3c245cSPedro Tammela * @protocol: protocol (0, ...) 12018a3c245cSPedro Tammela * @res: new socket 12028a3c245cSPedro Tammela * 12038a3c245cSPedro Tammela * Creates a new socket and assigns it to @res, passing through LSM. 12048a3c245cSPedro Tammela * The new socket initialization is not complete, see kernel_accept(). 12058a3c245cSPedro Tammela * Returns 0 or an error. On failure @res is set to %NULL. 12068a3c245cSPedro Tammela * This function internally uses GFP_KERNEL. 12078a3c245cSPedro Tammela */ 12088a3c245cSPedro Tammela 12091da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res) 12101da177e4SLinus Torvalds { 12111da177e4SLinus Torvalds int err; 12121da177e4SLinus Torvalds struct socket *sock = NULL; 12131da177e4SLinus Torvalds 12141da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, 1); 12151da177e4SLinus Torvalds if (err) 12161da177e4SLinus Torvalds goto out; 12171da177e4SLinus Torvalds 12181da177e4SLinus Torvalds sock = sock_alloc(); 12191da177e4SLinus Torvalds if (!sock) { 12201da177e4SLinus Torvalds err = -ENOMEM; 12211da177e4SLinus Torvalds goto out; 12221da177e4SLinus Torvalds } 12231da177e4SLinus Torvalds 12241da177e4SLinus Torvalds sock->type = type; 12257420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, 1); 12267420ed23SVenkat Yekkirala if (err) 12277420ed23SVenkat Yekkirala goto out_release; 12287420ed23SVenkat Yekkirala 12291da177e4SLinus Torvalds out: 12301da177e4SLinus Torvalds *res = sock; 12311da177e4SLinus Torvalds return err; 12327420ed23SVenkat Yekkirala out_release: 12337420ed23SVenkat Yekkirala sock_release(sock); 12347420ed23SVenkat Yekkirala sock = NULL; 12357420ed23SVenkat Yekkirala goto out; 12361da177e4SLinus Torvalds } 1237c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite); 12381da177e4SLinus Torvalds 12391da177e4SLinus Torvalds /* No kernel lock held - perfect */ 1240ade994f4SAl Viro static __poll_t sock_poll(struct file *file, poll_table *wait) 12411da177e4SLinus Torvalds { 12423cafb376SChristoph Hellwig struct socket *sock = file->private_data; 1243a331de3bSChristoph Hellwig __poll_t events = poll_requested_events(wait), flag = 0; 12441da177e4SLinus Torvalds 1245e88958e6SChristoph Hellwig if (!sock->ops->poll) 1246e88958e6SChristoph Hellwig return 0; 1247f641f13bSChristoph Hellwig 1248a331de3bSChristoph Hellwig if (sk_can_busy_loop(sock->sk)) { 1249f641f13bSChristoph Hellwig /* poll once if requested by the syscall */ 1250a331de3bSChristoph Hellwig if (events & POLL_BUSY_LOOP) 1251f641f13bSChristoph Hellwig sk_busy_loop(sock->sk, 1); 1252a331de3bSChristoph Hellwig 1253a331de3bSChristoph Hellwig /* if this socket can poll_ll, tell the system call */ 1254a331de3bSChristoph Hellwig flag = POLL_BUSY_LOOP; 1255a331de3bSChristoph Hellwig } 1256a331de3bSChristoph Hellwig 1257a331de3bSChristoph Hellwig return sock->ops->poll(file, sock, wait) | flag; 12581da177e4SLinus Torvalds } 12591da177e4SLinus Torvalds 12601da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma) 12611da177e4SLinus Torvalds { 1262b69aee04SEric Dumazet struct socket *sock = file->private_data; 12631da177e4SLinus Torvalds 12641da177e4SLinus Torvalds return sock->ops->mmap(file, sock, vma); 12651da177e4SLinus Torvalds } 12661da177e4SLinus Torvalds 126720380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp) 12681da177e4SLinus Torvalds { 12696d8c50dcSCong Wang __sock_release(SOCKET_I(inode), inode); 12701da177e4SLinus Torvalds return 0; 12711da177e4SLinus Torvalds } 12721da177e4SLinus Torvalds 12731da177e4SLinus Torvalds /* 12741da177e4SLinus Torvalds * Update the socket async list 12751da177e4SLinus Torvalds * 12761da177e4SLinus Torvalds * Fasync_list locking strategy. 12771da177e4SLinus Torvalds * 12781da177e4SLinus Torvalds * 1. fasync_list is modified only under process context socket lock 12791da177e4SLinus Torvalds * i.e. under semaphore. 12801da177e4SLinus Torvalds * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) 1281989a2979SEric Dumazet * or under socket lock 12821da177e4SLinus Torvalds */ 12831da177e4SLinus Torvalds 12841da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on) 12851da177e4SLinus Torvalds { 1286989a2979SEric Dumazet struct socket *sock = filp->private_data; 1287989a2979SEric Dumazet struct sock *sk = sock->sk; 1288333f7909SAl Viro struct socket_wq *wq = &sock->wq; 12891da177e4SLinus Torvalds 1290989a2979SEric Dumazet if (sk == NULL) 12911da177e4SLinus Torvalds return -EINVAL; 12921da177e4SLinus Torvalds 12931da177e4SLinus Torvalds lock_sock(sk); 1294eaefd110SEric Dumazet fasync_helper(fd, filp, on, &wq->fasync_list); 12951da177e4SLinus Torvalds 1296eaefd110SEric Dumazet if (!wq->fasync_list) 1297bcdce719SEric Dumazet sock_reset_flag(sk, SOCK_FASYNC); 1298989a2979SEric Dumazet else 1299989a2979SEric Dumazet sock_set_flag(sk, SOCK_FASYNC); 13001da177e4SLinus Torvalds 1301989a2979SEric Dumazet release_sock(sk); 13021da177e4SLinus Torvalds return 0; 13031da177e4SLinus Torvalds } 13041da177e4SLinus Torvalds 1305ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */ 13061da177e4SLinus Torvalds 1307ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band) 13081da177e4SLinus Torvalds { 1309ceb5d58bSEric Dumazet if (!wq || !wq->fasync_list) 1310ceb5d58bSEric Dumazet return -1; 131143815482SEric Dumazet 131289bddce5SStephen Hemminger switch (how) { 13138d8ad9d7SPavel Emelyanov case SOCK_WAKE_WAITD: 1314ceb5d58bSEric Dumazet if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags)) 13151da177e4SLinus Torvalds break; 13161da177e4SLinus Torvalds goto call_kill; 13178d8ad9d7SPavel Emelyanov case SOCK_WAKE_SPACE: 1318ceb5d58bSEric Dumazet if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags)) 13191da177e4SLinus Torvalds break; 13201da177e4SLinus Torvalds /* fall through */ 13218d8ad9d7SPavel Emelyanov case SOCK_WAKE_IO: 13221da177e4SLinus Torvalds call_kill: 132343815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGIO, band); 13241da177e4SLinus Torvalds break; 13258d8ad9d7SPavel Emelyanov case SOCK_WAKE_URG: 132643815482SEric Dumazet kill_fasync(&wq->fasync_list, SIGURG, band); 13271da177e4SLinus Torvalds } 1328ceb5d58bSEric Dumazet 13291da177e4SLinus Torvalds return 0; 13301da177e4SLinus Torvalds } 1331c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async); 13321da177e4SLinus Torvalds 13338a3c245cSPedro Tammela /** 13348a3c245cSPedro Tammela * __sock_create - creates a socket 13358a3c245cSPedro Tammela * @net: net namespace 13368a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...) 13378a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...) 13388a3c245cSPedro Tammela * @protocol: protocol (0, ...) 13398a3c245cSPedro Tammela * @res: new socket 13408a3c245cSPedro Tammela * @kern: boolean for kernel space sockets 13418a3c245cSPedro Tammela * 13428a3c245cSPedro Tammela * Creates a new socket and assigns it to @res, passing through LSM. 13438a3c245cSPedro Tammela * Returns 0 or an error. On failure @res is set to %NULL. @kern must 13448a3c245cSPedro Tammela * be set to true if the socket resides in kernel space. 13458a3c245cSPedro Tammela * This function internally uses GFP_KERNEL. 13468a3c245cSPedro Tammela */ 13478a3c245cSPedro Tammela 1348721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol, 134989bddce5SStephen Hemminger struct socket **res, int kern) 13501da177e4SLinus Torvalds { 13511da177e4SLinus Torvalds int err; 13521da177e4SLinus Torvalds struct socket *sock; 135355737fdaSStephen Hemminger const struct net_proto_family *pf; 13541da177e4SLinus Torvalds 13551da177e4SLinus Torvalds /* 13561da177e4SLinus Torvalds * Check protocol is in range 13571da177e4SLinus Torvalds */ 13581da177e4SLinus Torvalds if (family < 0 || family >= NPROTO) 13591da177e4SLinus Torvalds return -EAFNOSUPPORT; 13601da177e4SLinus Torvalds if (type < 0 || type >= SOCK_MAX) 13611da177e4SLinus Torvalds return -EINVAL; 13621da177e4SLinus Torvalds 13631da177e4SLinus Torvalds /* Compatibility. 13641da177e4SLinus Torvalds 13651da177e4SLinus Torvalds This uglymoron is moved from INET layer to here to avoid 13661da177e4SLinus Torvalds deadlock in module load. 13671da177e4SLinus Torvalds */ 13681da177e4SLinus Torvalds if (family == PF_INET && type == SOCK_PACKET) { 1369f3c98690Sliping.zhang pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n", 137089bddce5SStephen Hemminger current->comm); 13711da177e4SLinus Torvalds family = PF_PACKET; 13721da177e4SLinus Torvalds } 13731da177e4SLinus Torvalds 13741da177e4SLinus Torvalds err = security_socket_create(family, type, protocol, kern); 13751da177e4SLinus Torvalds if (err) 13761da177e4SLinus Torvalds return err; 13771da177e4SLinus Torvalds 137855737fdaSStephen Hemminger /* 137955737fdaSStephen Hemminger * Allocate the socket and allow the family to set things up. if 138055737fdaSStephen Hemminger * the protocol is 0, the family is instructed to select an appropriate 138155737fdaSStephen Hemminger * default. 138255737fdaSStephen Hemminger */ 138355737fdaSStephen Hemminger sock = sock_alloc(); 138455737fdaSStephen Hemminger if (!sock) { 1385e87cc472SJoe Perches net_warn_ratelimited("socket: no more sockets\n"); 138655737fdaSStephen Hemminger return -ENFILE; /* Not exactly a match, but its the 138755737fdaSStephen Hemminger closest posix thing */ 138855737fdaSStephen Hemminger } 138955737fdaSStephen Hemminger 139055737fdaSStephen Hemminger sock->type = type; 139155737fdaSStephen Hemminger 139295a5afcaSJohannes Berg #ifdef CONFIG_MODULES 13931da177e4SLinus Torvalds /* Attempt to load a protocol module if the find failed. 13941da177e4SLinus Torvalds * 13951da177e4SLinus Torvalds * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user 13961da177e4SLinus Torvalds * requested real, full-featured networking support upon configuration. 13971da177e4SLinus Torvalds * Otherwise module support will break! 13981da177e4SLinus Torvalds */ 1399190683a9SEric Dumazet if (rcu_access_pointer(net_families[family]) == NULL) 14001da177e4SLinus Torvalds request_module("net-pf-%d", family); 14011da177e4SLinus Torvalds #endif 14021da177e4SLinus Torvalds 140355737fdaSStephen Hemminger rcu_read_lock(); 140455737fdaSStephen Hemminger pf = rcu_dereference(net_families[family]); 14051da177e4SLinus Torvalds err = -EAFNOSUPPORT; 140655737fdaSStephen Hemminger if (!pf) 140755737fdaSStephen Hemminger goto out_release; 14081da177e4SLinus Torvalds 14091da177e4SLinus Torvalds /* 14101da177e4SLinus Torvalds * We will call the ->create function, that possibly is in a loadable 14111da177e4SLinus Torvalds * module, so we have to bump that loadable module refcnt first. 14121da177e4SLinus Torvalds */ 141355737fdaSStephen Hemminger if (!try_module_get(pf->owner)) 14141da177e4SLinus Torvalds goto out_release; 14151da177e4SLinus Torvalds 141655737fdaSStephen Hemminger /* Now protected by module ref count */ 141755737fdaSStephen Hemminger rcu_read_unlock(); 141855737fdaSStephen Hemminger 14193f378b68SEric Paris err = pf->create(net, sock, protocol, kern); 142055737fdaSStephen Hemminger if (err < 0) 14211da177e4SLinus Torvalds goto out_module_put; 1422a79af59eSFrank Filz 14231da177e4SLinus Torvalds /* 14241da177e4SLinus Torvalds * Now to bump the refcnt of the [loadable] module that owns this 14251da177e4SLinus Torvalds * socket at sock_release time we decrement its refcnt. 14261da177e4SLinus Torvalds */ 142755737fdaSStephen Hemminger if (!try_module_get(sock->ops->owner)) 142855737fdaSStephen Hemminger goto out_module_busy; 142955737fdaSStephen Hemminger 14301da177e4SLinus Torvalds /* 14311da177e4SLinus Torvalds * Now that we're done with the ->create function, the [loadable] 14321da177e4SLinus Torvalds * module can have its refcnt decremented 14331da177e4SLinus Torvalds */ 143455737fdaSStephen Hemminger module_put(pf->owner); 14357420ed23SVenkat Yekkirala err = security_socket_post_create(sock, family, type, protocol, kern); 14367420ed23SVenkat Yekkirala if (err) 14373b185525SHerbert Xu goto out_sock_release; 143855737fdaSStephen Hemminger *res = sock; 14391da177e4SLinus Torvalds 144055737fdaSStephen Hemminger return 0; 144155737fdaSStephen Hemminger 144255737fdaSStephen Hemminger out_module_busy: 144355737fdaSStephen Hemminger err = -EAFNOSUPPORT; 14441da177e4SLinus Torvalds out_module_put: 144555737fdaSStephen Hemminger sock->ops = NULL; 144655737fdaSStephen Hemminger module_put(pf->owner); 144755737fdaSStephen Hemminger out_sock_release: 14481da177e4SLinus Torvalds sock_release(sock); 144955737fdaSStephen Hemminger return err; 145055737fdaSStephen Hemminger 145155737fdaSStephen Hemminger out_release: 145255737fdaSStephen Hemminger rcu_read_unlock(); 145355737fdaSStephen Hemminger goto out_sock_release; 14541da177e4SLinus Torvalds } 1455721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create); 14561da177e4SLinus Torvalds 14578a3c245cSPedro Tammela /** 14588a3c245cSPedro Tammela * sock_create - creates a socket 14598a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...) 14608a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...) 14618a3c245cSPedro Tammela * @protocol: protocol (0, ...) 14628a3c245cSPedro Tammela * @res: new socket 14638a3c245cSPedro Tammela * 14648a3c245cSPedro Tammela * A wrapper around __sock_create(). 14658a3c245cSPedro Tammela * Returns 0 or an error. This function internally uses GFP_KERNEL. 14668a3c245cSPedro Tammela */ 14678a3c245cSPedro Tammela 14681da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res) 14691da177e4SLinus Torvalds { 14701b8d7ae4SEric W. Biederman return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0); 14711da177e4SLinus Torvalds } 1472c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create); 14731da177e4SLinus Torvalds 14748a3c245cSPedro Tammela /** 14758a3c245cSPedro Tammela * sock_create_kern - creates a socket (kernel space) 14768a3c245cSPedro Tammela * @net: net namespace 14778a3c245cSPedro Tammela * @family: protocol family (AF_INET, ...) 14788a3c245cSPedro Tammela * @type: communication type (SOCK_STREAM, ...) 14798a3c245cSPedro Tammela * @protocol: protocol (0, ...) 14808a3c245cSPedro Tammela * @res: new socket 14818a3c245cSPedro Tammela * 14828a3c245cSPedro Tammela * A wrapper around __sock_create(). 14838a3c245cSPedro Tammela * Returns 0 or an error. This function internally uses GFP_KERNEL. 14848a3c245cSPedro Tammela */ 14858a3c245cSPedro Tammela 1486eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res) 14871da177e4SLinus Torvalds { 1488eeb1bd5cSEric W. Biederman return __sock_create(net, family, type, protocol, res, 1); 14891da177e4SLinus Torvalds } 1490c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern); 14911da177e4SLinus Torvalds 14929d6a15c3SDominik Brodowski int __sys_socket(int family, int type, int protocol) 14931da177e4SLinus Torvalds { 14941da177e4SLinus Torvalds int retval; 14951da177e4SLinus Torvalds struct socket *sock; 1496a677a039SUlrich Drepper int flags; 1497a677a039SUlrich Drepper 1498e38b36f3SUlrich Drepper /* Check the SOCK_* constants for consistency. */ 1499e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); 1500e38b36f3SUlrich Drepper BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); 1501e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); 1502e38b36f3SUlrich Drepper BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); 1503e38b36f3SUlrich Drepper 1504a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 150577d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1506a677a039SUlrich Drepper return -EINVAL; 1507a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 15081da177e4SLinus Torvalds 1509aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1510aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1511aaca0bdcSUlrich Drepper 15121da177e4SLinus Torvalds retval = sock_create(family, type, protocol, &sock); 15131da177e4SLinus Torvalds if (retval < 0) 15141da177e4SLinus Torvalds return retval; 15151da177e4SLinus Torvalds 15168e1611e2SAl Viro return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); 15171da177e4SLinus Torvalds } 15181da177e4SLinus Torvalds 15199d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) 15209d6a15c3SDominik Brodowski { 15219d6a15c3SDominik Brodowski return __sys_socket(family, type, protocol); 15229d6a15c3SDominik Brodowski } 15239d6a15c3SDominik Brodowski 15241da177e4SLinus Torvalds /* 15251da177e4SLinus Torvalds * Create a pair of connected sockets. 15261da177e4SLinus Torvalds */ 15271da177e4SLinus Torvalds 15286debc8d8SDominik Brodowski int __sys_socketpair(int family, int type, int protocol, int __user *usockvec) 15291da177e4SLinus Torvalds { 15301da177e4SLinus Torvalds struct socket *sock1, *sock2; 15311da177e4SLinus Torvalds int fd1, fd2, err; 1532db349509SAl Viro struct file *newfile1, *newfile2; 1533a677a039SUlrich Drepper int flags; 1534a677a039SUlrich Drepper 1535a677a039SUlrich Drepper flags = type & ~SOCK_TYPE_MASK; 153677d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1537a677a039SUlrich Drepper return -EINVAL; 1538a677a039SUlrich Drepper type &= SOCK_TYPE_MASK; 15391da177e4SLinus Torvalds 1540aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1541aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1542aaca0bdcSUlrich Drepper 15431da177e4SLinus Torvalds /* 1544016a266bSAl Viro * reserve descriptors and make sure we won't fail 1545016a266bSAl Viro * to return them to userland. 1546016a266bSAl Viro */ 1547016a266bSAl Viro fd1 = get_unused_fd_flags(flags); 1548016a266bSAl Viro if (unlikely(fd1 < 0)) 1549016a266bSAl Viro return fd1; 1550016a266bSAl Viro 1551016a266bSAl Viro fd2 = get_unused_fd_flags(flags); 1552016a266bSAl Viro if (unlikely(fd2 < 0)) { 1553016a266bSAl Viro put_unused_fd(fd1); 1554016a266bSAl Viro return fd2; 1555016a266bSAl Viro } 1556016a266bSAl Viro 1557016a266bSAl Viro err = put_user(fd1, &usockvec[0]); 1558016a266bSAl Viro if (err) 1559016a266bSAl Viro goto out; 1560016a266bSAl Viro 1561016a266bSAl Viro err = put_user(fd2, &usockvec[1]); 1562016a266bSAl Viro if (err) 1563016a266bSAl Viro goto out; 1564016a266bSAl Viro 1565016a266bSAl Viro /* 15661da177e4SLinus Torvalds * Obtain the first socket and check if the underlying protocol 15671da177e4SLinus Torvalds * supports the socketpair call. 15681da177e4SLinus Torvalds */ 15691da177e4SLinus Torvalds 15701da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock1); 1571016a266bSAl Viro if (unlikely(err < 0)) 15721da177e4SLinus Torvalds goto out; 15731da177e4SLinus Torvalds 15741da177e4SLinus Torvalds err = sock_create(family, type, protocol, &sock2); 1575016a266bSAl Viro if (unlikely(err < 0)) { 1576016a266bSAl Viro sock_release(sock1); 1577016a266bSAl Viro goto out; 1578bf3c23d1SDavid S. Miller } 1579d73aa286SYann Droneaud 1580d47cd945SDavid Herrmann err = security_socket_socketpair(sock1, sock2); 1581d47cd945SDavid Herrmann if (unlikely(err)) { 1582d47cd945SDavid Herrmann sock_release(sock2); 1583d47cd945SDavid Herrmann sock_release(sock1); 1584d47cd945SDavid Herrmann goto out; 1585d47cd945SDavid Herrmann } 1586d47cd945SDavid Herrmann 1587016a266bSAl Viro err = sock1->ops->socketpair(sock1, sock2); 1588016a266bSAl Viro if (unlikely(err < 0)) { 1589016a266bSAl Viro sock_release(sock2); 1590016a266bSAl Viro sock_release(sock1); 1591016a266bSAl Viro goto out; 159228407630SAl Viro } 159328407630SAl Viro 1594aab174f0SLinus Torvalds newfile1 = sock_alloc_file(sock1, flags, NULL); 1595b5ffe634SViresh Kumar if (IS_ERR(newfile1)) { 159628407630SAl Viro err = PTR_ERR(newfile1); 1597016a266bSAl Viro sock_release(sock2); 1598016a266bSAl Viro goto out; 159928407630SAl Viro } 160028407630SAl Viro 1601aab174f0SLinus Torvalds newfile2 = sock_alloc_file(sock2, flags, NULL); 160228407630SAl Viro if (IS_ERR(newfile2)) { 160328407630SAl Viro err = PTR_ERR(newfile2); 1604016a266bSAl Viro fput(newfile1); 1605016a266bSAl Viro goto out; 1606db349509SAl Viro } 1607db349509SAl Viro 1608157cf649SAl Viro audit_fd_pair(fd1, fd2); 1609d73aa286SYann Droneaud 1610db349509SAl Viro fd_install(fd1, newfile1); 1611db349509SAl Viro fd_install(fd2, newfile2); 16121da177e4SLinus Torvalds return 0; 16131da177e4SLinus Torvalds 16141da177e4SLinus Torvalds out: 1615016a266bSAl Viro put_unused_fd(fd2); 1616016a266bSAl Viro put_unused_fd(fd1); 16171da177e4SLinus Torvalds return err; 16181da177e4SLinus Torvalds } 16191da177e4SLinus Torvalds 16206debc8d8SDominik Brodowski SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, 16216debc8d8SDominik Brodowski int __user *, usockvec) 16226debc8d8SDominik Brodowski { 16236debc8d8SDominik Brodowski return __sys_socketpair(family, type, protocol, usockvec); 16246debc8d8SDominik Brodowski } 16256debc8d8SDominik Brodowski 16261da177e4SLinus Torvalds /* 16271da177e4SLinus Torvalds * Bind a name to a socket. Nothing much to do here since it's 16281da177e4SLinus Torvalds * the protocol's responsibility to handle the local address. 16291da177e4SLinus Torvalds * 16301da177e4SLinus Torvalds * We move the socket address to kernel space before we call 16311da177e4SLinus Torvalds * the protocol layer (having also checked the address is ok). 16321da177e4SLinus Torvalds */ 16331da177e4SLinus Torvalds 1634a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) 16351da177e4SLinus Torvalds { 16361da177e4SLinus Torvalds struct socket *sock; 1637230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 16386cb153caSBenjamin LaHaise int err, fput_needed; 16391da177e4SLinus Torvalds 164089bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 164189bddce5SStephen Hemminger if (sock) { 164243db362dSMaciej Żenczykowski err = move_addr_to_kernel(umyaddr, addrlen, &address); 1643068b88ccSJakub Sitnicki if (!err) { 164489bddce5SStephen Hemminger err = security_socket_bind(sock, 1645230b1839SYOSHIFUJI Hideaki (struct sockaddr *)&address, 164689bddce5SStephen Hemminger addrlen); 16476cb153caSBenjamin LaHaise if (!err) 16486cb153caSBenjamin LaHaise err = sock->ops->bind(sock, 164989bddce5SStephen Hemminger (struct sockaddr *) 1650230b1839SYOSHIFUJI Hideaki &address, addrlen); 16511da177e4SLinus Torvalds } 16526cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16531da177e4SLinus Torvalds } 16541da177e4SLinus Torvalds return err; 16551da177e4SLinus Torvalds } 16561da177e4SLinus Torvalds 1657a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) 1658a87d35d8SDominik Brodowski { 1659a87d35d8SDominik Brodowski return __sys_bind(fd, umyaddr, addrlen); 1660a87d35d8SDominik Brodowski } 1661a87d35d8SDominik Brodowski 16621da177e4SLinus Torvalds /* 16631da177e4SLinus Torvalds * Perform a listen. Basically, we allow the protocol to do anything 16641da177e4SLinus Torvalds * necessary for a listen, and if that works, we mark the socket as 16651da177e4SLinus Torvalds * ready for listening. 16661da177e4SLinus Torvalds */ 16671da177e4SLinus Torvalds 166825e290eeSDominik Brodowski int __sys_listen(int fd, int backlog) 16691da177e4SLinus Torvalds { 16701da177e4SLinus Torvalds struct socket *sock; 16716cb153caSBenjamin LaHaise int err, fput_needed; 1672b8e1f9b5SPavel Emelyanov int somaxconn; 16731da177e4SLinus Torvalds 167489bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 167589bddce5SStephen Hemminger if (sock) { 16768efa6e93SPavel Emelyanov somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 167795c96174SEric Dumazet if ((unsigned int)backlog > somaxconn) 1678b8e1f9b5SPavel Emelyanov backlog = somaxconn; 16791da177e4SLinus Torvalds 16801da177e4SLinus Torvalds err = security_socket_listen(sock, backlog); 16816cb153caSBenjamin LaHaise if (!err) 16821da177e4SLinus Torvalds err = sock->ops->listen(sock, backlog); 16836cb153caSBenjamin LaHaise 16846cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 16851da177e4SLinus Torvalds } 16861da177e4SLinus Torvalds return err; 16871da177e4SLinus Torvalds } 16881da177e4SLinus Torvalds 168925e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog) 169025e290eeSDominik Brodowski { 169125e290eeSDominik Brodowski return __sys_listen(fd, backlog); 169225e290eeSDominik Brodowski } 169325e290eeSDominik Brodowski 1694de2ea4b6SJens Axboe int __sys_accept4_file(struct file *file, unsigned file_flags, 1695de2ea4b6SJens Axboe struct sockaddr __user *upeer_sockaddr, 16964541e805SDominik Brodowski int __user *upeer_addrlen, int flags) 16971da177e4SLinus Torvalds { 16981da177e4SLinus Torvalds struct socket *sock, *newsock; 169939d8c1b6SDavid S. Miller struct file *newfile; 1700de2ea4b6SJens Axboe int err, len, newfd; 1701230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 17021da177e4SLinus Torvalds 170377d27200SUlrich Drepper if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 1704aaca0bdcSUlrich Drepper return -EINVAL; 1705aaca0bdcSUlrich Drepper 1706aaca0bdcSUlrich Drepper if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) 1707aaca0bdcSUlrich Drepper flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 1708aaca0bdcSUlrich Drepper 1709de2ea4b6SJens Axboe sock = sock_from_file(file, &err); 17101da177e4SLinus Torvalds if (!sock) 17111da177e4SLinus Torvalds goto out; 17121da177e4SLinus Torvalds 17131da177e4SLinus Torvalds err = -ENFILE; 1714c6d409cfSEric Dumazet newsock = sock_alloc(); 1715c6d409cfSEric Dumazet if (!newsock) 1716de2ea4b6SJens Axboe goto out; 17171da177e4SLinus Torvalds 17181da177e4SLinus Torvalds newsock->type = sock->type; 17191da177e4SLinus Torvalds newsock->ops = sock->ops; 17201da177e4SLinus Torvalds 17211da177e4SLinus Torvalds /* 17221da177e4SLinus Torvalds * We don't need try_module_get here, as the listening socket (sock) 17231da177e4SLinus Torvalds * has the protocol module (sock->ops->owner) held. 17241da177e4SLinus Torvalds */ 17251da177e4SLinus Torvalds __module_get(newsock->ops->owner); 17261da177e4SLinus Torvalds 172728407630SAl Viro newfd = get_unused_fd_flags(flags); 172839d8c1b6SDavid S. Miller if (unlikely(newfd < 0)) { 172939d8c1b6SDavid S. Miller err = newfd; 17309a1875e6SDavid S. Miller sock_release(newsock); 1731de2ea4b6SJens Axboe goto out; 173239d8c1b6SDavid S. Miller } 1733aab174f0SLinus Torvalds newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); 1734b5ffe634SViresh Kumar if (IS_ERR(newfile)) { 173528407630SAl Viro err = PTR_ERR(newfile); 173628407630SAl Viro put_unused_fd(newfd); 1737de2ea4b6SJens Axboe goto out; 173828407630SAl Viro } 173939d8c1b6SDavid S. Miller 1740a79af59eSFrank Filz err = security_socket_accept(sock, newsock); 1741a79af59eSFrank Filz if (err) 174239d8c1b6SDavid S. Miller goto out_fd; 1743a79af59eSFrank Filz 1744de2ea4b6SJens Axboe err = sock->ops->accept(sock, newsock, sock->file->f_flags | file_flags, 1745de2ea4b6SJens Axboe false); 17461da177e4SLinus Torvalds if (err < 0) 174739d8c1b6SDavid S. Miller goto out_fd; 17481da177e4SLinus Torvalds 17491da177e4SLinus Torvalds if (upeer_sockaddr) { 17509b2c45d4SDenys Vlasenko len = newsock->ops->getname(newsock, 17519b2c45d4SDenys Vlasenko (struct sockaddr *)&address, 2); 17529b2c45d4SDenys Vlasenko if (len < 0) { 17531da177e4SLinus Torvalds err = -ECONNABORTED; 175439d8c1b6SDavid S. Miller goto out_fd; 17551da177e4SLinus Torvalds } 175643db362dSMaciej Żenczykowski err = move_addr_to_user(&address, 1757230b1839SYOSHIFUJI Hideaki len, upeer_sockaddr, upeer_addrlen); 17581da177e4SLinus Torvalds if (err < 0) 175939d8c1b6SDavid S. Miller goto out_fd; 17601da177e4SLinus Torvalds } 17611da177e4SLinus Torvalds 17621da177e4SLinus Torvalds /* File flags are not inherited via accept() unlike another OSes. */ 17631da177e4SLinus Torvalds 176439d8c1b6SDavid S. Miller fd_install(newfd, newfile); 176539d8c1b6SDavid S. Miller err = newfd; 17661da177e4SLinus Torvalds out: 17671da177e4SLinus Torvalds return err; 176839d8c1b6SDavid S. Miller out_fd: 17699606a216SDavid S. Miller fput(newfile); 177039d8c1b6SDavid S. Miller put_unused_fd(newfd); 1771de2ea4b6SJens Axboe goto out; 1772de2ea4b6SJens Axboe 1773de2ea4b6SJens Axboe } 1774de2ea4b6SJens Axboe 1775de2ea4b6SJens Axboe /* 1776de2ea4b6SJens Axboe * For accept, we attempt to create a new socket, set up the link 1777de2ea4b6SJens Axboe * with the client, wake up the client, then return the new 1778de2ea4b6SJens Axboe * connected fd. We collect the address of the connector in kernel 1779de2ea4b6SJens Axboe * space and move it to user at the very end. This is unclean because 1780de2ea4b6SJens Axboe * we open the socket then return an error. 1781de2ea4b6SJens Axboe * 1782de2ea4b6SJens Axboe * 1003.1g adds the ability to recvmsg() to query connection pending 1783de2ea4b6SJens Axboe * status to recvmsg. We need to add that support in a way thats 1784de2ea4b6SJens Axboe * clean when we restructure accept also. 1785de2ea4b6SJens Axboe */ 1786de2ea4b6SJens Axboe 1787de2ea4b6SJens Axboe int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, 1788de2ea4b6SJens Axboe int __user *upeer_addrlen, int flags) 1789de2ea4b6SJens Axboe { 1790de2ea4b6SJens Axboe int ret = -EBADF; 1791de2ea4b6SJens Axboe struct fd f; 1792de2ea4b6SJens Axboe 1793de2ea4b6SJens Axboe f = fdget(fd); 1794de2ea4b6SJens Axboe if (f.file) { 1795de2ea4b6SJens Axboe ret = __sys_accept4_file(f.file, 0, upeer_sockaddr, 1796de2ea4b6SJens Axboe upeer_addrlen, flags); 1797de2ea4b6SJens Axboe if (f.flags) 1798de2ea4b6SJens Axboe fput(f.file); 1799de2ea4b6SJens Axboe } 1800de2ea4b6SJens Axboe 1801de2ea4b6SJens Axboe return ret; 18021da177e4SLinus Torvalds } 18031da177e4SLinus Torvalds 18044541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, 18054541e805SDominik Brodowski int __user *, upeer_addrlen, int, flags) 18064541e805SDominik Brodowski { 18074541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags); 18084541e805SDominik Brodowski } 18094541e805SDominik Brodowski 181020f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, 181120f37034SHeiko Carstens int __user *, upeer_addrlen) 1812aaca0bdcSUlrich Drepper { 18134541e805SDominik Brodowski return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); 1814aaca0bdcSUlrich Drepper } 1815aaca0bdcSUlrich Drepper 18161da177e4SLinus Torvalds /* 18171da177e4SLinus Torvalds * Attempt to connect to a socket with the server address. The address 18181da177e4SLinus Torvalds * is in user space so we verify it is OK and move it to kernel space. 18191da177e4SLinus Torvalds * 18201da177e4SLinus Torvalds * For 1003.1g we need to add clean support for a bind to AF_UNSPEC to 18211da177e4SLinus Torvalds * break bindings 18221da177e4SLinus Torvalds * 18231da177e4SLinus Torvalds * NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and 18241da177e4SLinus Torvalds * other SEQPACKET protocols that take time to connect() as it doesn't 18251da177e4SLinus Torvalds * include the -EINPROGRESS status for such sockets. 18261da177e4SLinus Torvalds */ 18271da177e4SLinus Torvalds 1828bd3ded31SJens Axboe int __sys_connect_file(struct file *file, struct sockaddr __user *uservaddr, 1829bd3ded31SJens Axboe int addrlen, int file_flags) 18301da177e4SLinus Torvalds { 18311da177e4SLinus Torvalds struct socket *sock; 1832230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 1833bd3ded31SJens Axboe int err; 18341da177e4SLinus Torvalds 1835bd3ded31SJens Axboe sock = sock_from_file(file, &err); 18361da177e4SLinus Torvalds if (!sock) 18371da177e4SLinus Torvalds goto out; 183843db362dSMaciej Żenczykowski err = move_addr_to_kernel(uservaddr, addrlen, &address); 18391da177e4SLinus Torvalds if (err < 0) 1840bd3ded31SJens Axboe goto out; 18411da177e4SLinus Torvalds 184289bddce5SStephen Hemminger err = 1843230b1839SYOSHIFUJI Hideaki security_socket_connect(sock, (struct sockaddr *)&address, addrlen); 18441da177e4SLinus Torvalds if (err) 1845bd3ded31SJens Axboe goto out; 18461da177e4SLinus Torvalds 1847230b1839SYOSHIFUJI Hideaki err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, 1848bd3ded31SJens Axboe sock->file->f_flags | file_flags); 18491da177e4SLinus Torvalds out: 18501da177e4SLinus Torvalds return err; 18511da177e4SLinus Torvalds } 18521da177e4SLinus Torvalds 1853bd3ded31SJens Axboe int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) 1854bd3ded31SJens Axboe { 1855bd3ded31SJens Axboe int ret = -EBADF; 1856bd3ded31SJens Axboe struct fd f; 1857bd3ded31SJens Axboe 1858bd3ded31SJens Axboe f = fdget(fd); 1859bd3ded31SJens Axboe if (f.file) { 1860bd3ded31SJens Axboe ret = __sys_connect_file(f.file, uservaddr, addrlen, 0); 1861bd3ded31SJens Axboe if (f.flags) 1862bd3ded31SJens Axboe fput(f.file); 1863bd3ded31SJens Axboe } 1864bd3ded31SJens Axboe 1865bd3ded31SJens Axboe return ret; 1866bd3ded31SJens Axboe } 1867bd3ded31SJens Axboe 18681387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, 18691387c2c2SDominik Brodowski int, addrlen) 18701387c2c2SDominik Brodowski { 18711387c2c2SDominik Brodowski return __sys_connect(fd, uservaddr, addrlen); 18721387c2c2SDominik Brodowski } 18731387c2c2SDominik Brodowski 18741da177e4SLinus Torvalds /* 18751da177e4SLinus Torvalds * Get the local address ('name') of a socket object. Move the obtained 18761da177e4SLinus Torvalds * name to user space. 18771da177e4SLinus Torvalds */ 18781da177e4SLinus Torvalds 18798882a107SDominik Brodowski int __sys_getsockname(int fd, struct sockaddr __user *usockaddr, 18808882a107SDominik Brodowski int __user *usockaddr_len) 18811da177e4SLinus Torvalds { 18821da177e4SLinus Torvalds struct socket *sock; 1883230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 18849b2c45d4SDenys Vlasenko int err, fput_needed; 18851da177e4SLinus Torvalds 18866cb153caSBenjamin LaHaise sock = sockfd_lookup_light(fd, &err, &fput_needed); 18871da177e4SLinus Torvalds if (!sock) 18881da177e4SLinus Torvalds goto out; 18891da177e4SLinus Torvalds 18901da177e4SLinus Torvalds err = security_socket_getsockname(sock); 18911da177e4SLinus Torvalds if (err) 18921da177e4SLinus Torvalds goto out_put; 18931da177e4SLinus Torvalds 18949b2c45d4SDenys Vlasenko err = sock->ops->getname(sock, (struct sockaddr *)&address, 0); 18959b2c45d4SDenys Vlasenko if (err < 0) 18961da177e4SLinus Torvalds goto out_put; 18979b2c45d4SDenys Vlasenko /* "err" is actually length in this case */ 18989b2c45d4SDenys Vlasenko err = move_addr_to_user(&address, err, usockaddr, usockaddr_len); 18991da177e4SLinus Torvalds 19001da177e4SLinus Torvalds out_put: 19016cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19021da177e4SLinus Torvalds out: 19031da177e4SLinus Torvalds return err; 19041da177e4SLinus Torvalds } 19051da177e4SLinus Torvalds 19068882a107SDominik Brodowski SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr, 19078882a107SDominik Brodowski int __user *, usockaddr_len) 19088882a107SDominik Brodowski { 19098882a107SDominik Brodowski return __sys_getsockname(fd, usockaddr, usockaddr_len); 19108882a107SDominik Brodowski } 19118882a107SDominik Brodowski 19121da177e4SLinus Torvalds /* 19131da177e4SLinus Torvalds * Get the remote address ('name') of a socket object. Move the obtained 19141da177e4SLinus Torvalds * name to user space. 19151da177e4SLinus Torvalds */ 19161da177e4SLinus Torvalds 1917b21c8f83SDominik Brodowski int __sys_getpeername(int fd, struct sockaddr __user *usockaddr, 1918b21c8f83SDominik Brodowski int __user *usockaddr_len) 19191da177e4SLinus Torvalds { 19201da177e4SLinus Torvalds struct socket *sock; 1921230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 19229b2c45d4SDenys Vlasenko int err, fput_needed; 19231da177e4SLinus Torvalds 192489bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 192589bddce5SStephen Hemminger if (sock != NULL) { 19261da177e4SLinus Torvalds err = security_socket_getpeername(sock); 19271da177e4SLinus Torvalds if (err) { 19286cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19291da177e4SLinus Torvalds return err; 19301da177e4SLinus Torvalds } 19311da177e4SLinus Torvalds 19329b2c45d4SDenys Vlasenko err = sock->ops->getname(sock, (struct sockaddr *)&address, 1); 19339b2c45d4SDenys Vlasenko if (err >= 0) 19349b2c45d4SDenys Vlasenko /* "err" is actually length in this case */ 19359b2c45d4SDenys Vlasenko err = move_addr_to_user(&address, err, usockaddr, 193689bddce5SStephen Hemminger usockaddr_len); 19376cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 19381da177e4SLinus Torvalds } 19391da177e4SLinus Torvalds return err; 19401da177e4SLinus Torvalds } 19411da177e4SLinus Torvalds 1942b21c8f83SDominik Brodowski SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, 1943b21c8f83SDominik Brodowski int __user *, usockaddr_len) 1944b21c8f83SDominik Brodowski { 1945b21c8f83SDominik Brodowski return __sys_getpeername(fd, usockaddr, usockaddr_len); 1946b21c8f83SDominik Brodowski } 1947b21c8f83SDominik Brodowski 19481da177e4SLinus Torvalds /* 19491da177e4SLinus Torvalds * Send a datagram to a given address. We move the address into kernel 19501da177e4SLinus Torvalds * space and check the user space data area is readable before invoking 19511da177e4SLinus Torvalds * the protocol. 19521da177e4SLinus Torvalds */ 1953211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, 1954211b634bSDominik Brodowski struct sockaddr __user *addr, int addr_len) 19551da177e4SLinus Torvalds { 19561da177e4SLinus Torvalds struct socket *sock; 1957230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 19581da177e4SLinus Torvalds int err; 19591da177e4SLinus Torvalds struct msghdr msg; 19601da177e4SLinus Torvalds struct iovec iov; 19616cb153caSBenjamin LaHaise int fput_needed; 19621da177e4SLinus Torvalds 1963602bd0e9SAl Viro err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter); 1964602bd0e9SAl Viro if (unlikely(err)) 1965602bd0e9SAl Viro return err; 1966de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 1967de0fa95cSPavel Emelyanov if (!sock) 19684387ff75SDavid S. Miller goto out; 19696cb153caSBenjamin LaHaise 19701da177e4SLinus Torvalds msg.msg_name = NULL; 19711da177e4SLinus Torvalds msg.msg_control = NULL; 19721da177e4SLinus Torvalds msg.msg_controllen = 0; 19731da177e4SLinus Torvalds msg.msg_namelen = 0; 19746cb153caSBenjamin LaHaise if (addr) { 197543db362dSMaciej Żenczykowski err = move_addr_to_kernel(addr, addr_len, &address); 19761da177e4SLinus Torvalds if (err < 0) 19771da177e4SLinus Torvalds goto out_put; 1978230b1839SYOSHIFUJI Hideaki msg.msg_name = (struct sockaddr *)&address; 19791da177e4SLinus Torvalds msg.msg_namelen = addr_len; 19801da177e4SLinus Torvalds } 19811da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 19821da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 19831da177e4SLinus Torvalds msg.msg_flags = flags; 1984d8725c86SAl Viro err = sock_sendmsg(sock, &msg); 19851da177e4SLinus Torvalds 19861da177e4SLinus Torvalds out_put: 1987de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 19884387ff75SDavid S. Miller out: 19891da177e4SLinus Torvalds return err; 19901da177e4SLinus Torvalds } 19911da177e4SLinus Torvalds 1992211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, 1993211b634bSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr, 1994211b634bSDominik Brodowski int, addr_len) 1995211b634bSDominik Brodowski { 1996211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, addr, addr_len); 1997211b634bSDominik Brodowski } 1998211b634bSDominik Brodowski 19991da177e4SLinus Torvalds /* 20001da177e4SLinus Torvalds * Send a datagram down a socket. 20011da177e4SLinus Torvalds */ 20021da177e4SLinus Torvalds 20033e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, 200495c96174SEric Dumazet unsigned int, flags) 20051da177e4SLinus Torvalds { 2006211b634bSDominik Brodowski return __sys_sendto(fd, buff, len, flags, NULL, 0); 20071da177e4SLinus Torvalds } 20081da177e4SLinus Torvalds 20091da177e4SLinus Torvalds /* 20101da177e4SLinus Torvalds * Receive a frame from the socket and optionally record the address of the 20111da177e4SLinus Torvalds * sender. We verify the buffers are writable and if needed move the 20121da177e4SLinus Torvalds * sender address from kernel to user space. 20131da177e4SLinus Torvalds */ 20147a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, 20157a09e1ebSDominik Brodowski struct sockaddr __user *addr, int __user *addr_len) 20161da177e4SLinus Torvalds { 20171da177e4SLinus Torvalds struct socket *sock; 20181da177e4SLinus Torvalds struct iovec iov; 20191da177e4SLinus Torvalds struct msghdr msg; 2020230b1839SYOSHIFUJI Hideaki struct sockaddr_storage address; 20211da177e4SLinus Torvalds int err, err2; 20226cb153caSBenjamin LaHaise int fput_needed; 20231da177e4SLinus Torvalds 2024602bd0e9SAl Viro err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter); 2025602bd0e9SAl Viro if (unlikely(err)) 2026602bd0e9SAl Viro return err; 2027de0fa95cSPavel Emelyanov sock = sockfd_lookup_light(fd, &err, &fput_needed); 20281da177e4SLinus Torvalds if (!sock) 2029de0fa95cSPavel Emelyanov goto out; 20301da177e4SLinus Torvalds 20311da177e4SLinus Torvalds msg.msg_control = NULL; 20321da177e4SLinus Torvalds msg.msg_controllen = 0; 2033f3d33426SHannes Frederic Sowa /* Save some cycles and don't copy the address if not needed */ 2034f3d33426SHannes Frederic Sowa msg.msg_name = addr ? (struct sockaddr *)&address : NULL; 2035f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 2036f3d33426SHannes Frederic Sowa msg.msg_namelen = 0; 2037130ed5d1Stadeusz.struk@intel.com msg.msg_iocb = NULL; 20389f138fa6SAlexander Potapenko msg.msg_flags = 0; 20391da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 20401da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 20412da62906SAl Viro err = sock_recvmsg(sock, &msg, flags); 20421da177e4SLinus Torvalds 204389bddce5SStephen Hemminger if (err >= 0 && addr != NULL) { 204443db362dSMaciej Żenczykowski err2 = move_addr_to_user(&address, 2045230b1839SYOSHIFUJI Hideaki msg.msg_namelen, addr, addr_len); 20461da177e4SLinus Torvalds if (err2 < 0) 20471da177e4SLinus Torvalds err = err2; 20481da177e4SLinus Torvalds } 2049de0fa95cSPavel Emelyanov 2050de0fa95cSPavel Emelyanov fput_light(sock->file, fput_needed); 20514387ff75SDavid S. Miller out: 20521da177e4SLinus Torvalds return err; 20531da177e4SLinus Torvalds } 20541da177e4SLinus Torvalds 20557a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, 20567a09e1ebSDominik Brodowski unsigned int, flags, struct sockaddr __user *, addr, 20577a09e1ebSDominik Brodowski int __user *, addr_len) 20587a09e1ebSDominik Brodowski { 20597a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len); 20607a09e1ebSDominik Brodowski } 20617a09e1ebSDominik Brodowski 20621da177e4SLinus Torvalds /* 20631da177e4SLinus Torvalds * Receive a datagram from a socket. 20641da177e4SLinus Torvalds */ 20651da177e4SLinus Torvalds 2066b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size, 2067b7c0ddf5SJan Glauber unsigned int, flags) 20681da177e4SLinus Torvalds { 20697a09e1ebSDominik Brodowski return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); 20701da177e4SLinus Torvalds } 20711da177e4SLinus Torvalds 20721da177e4SLinus Torvalds /* 20731da177e4SLinus Torvalds * Set a socket option. Because we don't know the option lengths we have 20741da177e4SLinus Torvalds * to pass the user mode parameter for the protocols to sort out. 20751da177e4SLinus Torvalds */ 20761da177e4SLinus Torvalds 2077cc36dca0SDominik Brodowski static int __sys_setsockopt(int fd, int level, int optname, 2078cc36dca0SDominik Brodowski char __user *optval, int optlen) 20791da177e4SLinus Torvalds { 20800d01da6aSStanislav Fomichev mm_segment_t oldfs = get_fs(); 20810d01da6aSStanislav Fomichev char *kernel_optval = NULL; 20826cb153caSBenjamin LaHaise int err, fput_needed; 20831da177e4SLinus Torvalds struct socket *sock; 20841da177e4SLinus Torvalds 20851da177e4SLinus Torvalds if (optlen < 0) 20861da177e4SLinus Torvalds return -EINVAL; 20871da177e4SLinus Torvalds 208889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 208989bddce5SStephen Hemminger if (sock != NULL) { 20901da177e4SLinus Torvalds err = security_socket_setsockopt(sock, level, optname); 20916cb153caSBenjamin LaHaise if (err) 20926cb153caSBenjamin LaHaise goto out_put; 20931da177e4SLinus Torvalds 20940d01da6aSStanislav Fomichev err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, 20950d01da6aSStanislav Fomichev &optname, optval, &optlen, 20960d01da6aSStanislav Fomichev &kernel_optval); 20970d01da6aSStanislav Fomichev 20980d01da6aSStanislav Fomichev if (err < 0) { 20990d01da6aSStanislav Fomichev goto out_put; 21000d01da6aSStanislav Fomichev } else if (err > 0) { 21010d01da6aSStanislav Fomichev err = 0; 21020d01da6aSStanislav Fomichev goto out_put; 21030d01da6aSStanislav Fomichev } 21040d01da6aSStanislav Fomichev 21050d01da6aSStanislav Fomichev if (kernel_optval) { 21060d01da6aSStanislav Fomichev set_fs(KERNEL_DS); 21070d01da6aSStanislav Fomichev optval = (char __user __force *)kernel_optval; 21080d01da6aSStanislav Fomichev } 21090d01da6aSStanislav Fomichev 21101da177e4SLinus Torvalds if (level == SOL_SOCKET) 211189bddce5SStephen Hemminger err = 211289bddce5SStephen Hemminger sock_setsockopt(sock, level, optname, optval, 211389bddce5SStephen Hemminger optlen); 21141da177e4SLinus Torvalds else 211589bddce5SStephen Hemminger err = 211689bddce5SStephen Hemminger sock->ops->setsockopt(sock, level, optname, optval, 211789bddce5SStephen Hemminger optlen); 21180d01da6aSStanislav Fomichev 21190d01da6aSStanislav Fomichev if (kernel_optval) { 21200d01da6aSStanislav Fomichev set_fs(oldfs); 21210d01da6aSStanislav Fomichev kfree(kernel_optval); 21220d01da6aSStanislav Fomichev } 21236cb153caSBenjamin LaHaise out_put: 21246cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 21251da177e4SLinus Torvalds } 21261da177e4SLinus Torvalds return err; 21271da177e4SLinus Torvalds } 21281da177e4SLinus Torvalds 2129cc36dca0SDominik Brodowski SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, 2130cc36dca0SDominik Brodowski char __user *, optval, int, optlen) 2131cc36dca0SDominik Brodowski { 2132cc36dca0SDominik Brodowski return __sys_setsockopt(fd, level, optname, optval, optlen); 2133cc36dca0SDominik Brodowski } 2134cc36dca0SDominik Brodowski 21351da177e4SLinus Torvalds /* 21361da177e4SLinus Torvalds * Get a socket option. Because we don't know the option lengths we have 21371da177e4SLinus Torvalds * to pass a user mode parameter for the protocols to sort out. 21381da177e4SLinus Torvalds */ 21391da177e4SLinus Torvalds 214013a2d70eSDominik Brodowski static int __sys_getsockopt(int fd, int level, int optname, 214113a2d70eSDominik Brodowski char __user *optval, int __user *optlen) 21421da177e4SLinus Torvalds { 21436cb153caSBenjamin LaHaise int err, fput_needed; 21441da177e4SLinus Torvalds struct socket *sock; 21450d01da6aSStanislav Fomichev int max_optlen; 21461da177e4SLinus Torvalds 214789bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 214889bddce5SStephen Hemminger if (sock != NULL) { 21496cb153caSBenjamin LaHaise err = security_socket_getsockopt(sock, level, optname); 21506cb153caSBenjamin LaHaise if (err) 21516cb153caSBenjamin LaHaise goto out_put; 21521da177e4SLinus Torvalds 21530d01da6aSStanislav Fomichev max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen); 21540d01da6aSStanislav Fomichev 21551da177e4SLinus Torvalds if (level == SOL_SOCKET) 215689bddce5SStephen Hemminger err = 215789bddce5SStephen Hemminger sock_getsockopt(sock, level, optname, optval, 215889bddce5SStephen Hemminger optlen); 21591da177e4SLinus Torvalds else 216089bddce5SStephen Hemminger err = 216189bddce5SStephen Hemminger sock->ops->getsockopt(sock, level, optname, optval, 216289bddce5SStephen Hemminger optlen); 21630d01da6aSStanislav Fomichev 21640d01da6aSStanislav Fomichev err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname, 21650d01da6aSStanislav Fomichev optval, optlen, 21660d01da6aSStanislav Fomichev max_optlen, err); 21676cb153caSBenjamin LaHaise out_put: 21686cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 21691da177e4SLinus Torvalds } 21701da177e4SLinus Torvalds return err; 21711da177e4SLinus Torvalds } 21721da177e4SLinus Torvalds 217313a2d70eSDominik Brodowski SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, 217413a2d70eSDominik Brodowski char __user *, optval, int __user *, optlen) 217513a2d70eSDominik Brodowski { 217613a2d70eSDominik Brodowski return __sys_getsockopt(fd, level, optname, optval, optlen); 217713a2d70eSDominik Brodowski } 217813a2d70eSDominik Brodowski 21791da177e4SLinus Torvalds /* 21801da177e4SLinus Torvalds * Shutdown a socket. 21811da177e4SLinus Torvalds */ 21821da177e4SLinus Torvalds 2183005a1aeaSDominik Brodowski int __sys_shutdown(int fd, int how) 21841da177e4SLinus Torvalds { 21856cb153caSBenjamin LaHaise int err, fput_needed; 21861da177e4SLinus Torvalds struct socket *sock; 21871da177e4SLinus Torvalds 218889bddce5SStephen Hemminger sock = sockfd_lookup_light(fd, &err, &fput_needed); 218989bddce5SStephen Hemminger if (sock != NULL) { 21901da177e4SLinus Torvalds err = security_socket_shutdown(sock, how); 21916cb153caSBenjamin LaHaise if (!err) 21921da177e4SLinus Torvalds err = sock->ops->shutdown(sock, how); 21936cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 21941da177e4SLinus Torvalds } 21951da177e4SLinus Torvalds return err; 21961da177e4SLinus Torvalds } 21971da177e4SLinus Torvalds 2198005a1aeaSDominik Brodowski SYSCALL_DEFINE2(shutdown, int, fd, int, how) 2199005a1aeaSDominik Brodowski { 2200005a1aeaSDominik Brodowski return __sys_shutdown(fd, how); 2201005a1aeaSDominik Brodowski } 2202005a1aeaSDominik Brodowski 22031da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit 22041da177e4SLinus Torvalds * fields which are the same type (int / unsigned) on our platforms. 22051da177e4SLinus Torvalds */ 22061da177e4SLinus Torvalds #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) 22071da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) 22081da177e4SLinus Torvalds #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) 22091da177e4SLinus Torvalds 2210c71d8ebeSTetsuo Handa struct used_address { 2211c71d8ebeSTetsuo Handa struct sockaddr_storage name; 2212c71d8ebeSTetsuo Handa unsigned int name_len; 2213c71d8ebeSTetsuo Handa }; 2214c71d8ebeSTetsuo Handa 2215da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg, 221608adb7daSAl Viro struct user_msghdr __user *umsg, 221708adb7daSAl Viro struct sockaddr __user **save_addr, 221808adb7daSAl Viro struct iovec **iov) 22191661bf36SDan Carpenter { 2220ffb07550SAl Viro struct user_msghdr msg; 222108adb7daSAl Viro ssize_t err; 222208adb7daSAl Viro 2223ffb07550SAl Viro if (copy_from_user(&msg, umsg, sizeof(*umsg))) 22241661bf36SDan Carpenter return -EFAULT; 2225dbb490b9SMatthew Leach 2226864d9664SPaolo Abeni kmsg->msg_control = (void __force *)msg.msg_control; 2227ffb07550SAl Viro kmsg->msg_controllen = msg.msg_controllen; 2228ffb07550SAl Viro kmsg->msg_flags = msg.msg_flags; 2229ffb07550SAl Viro 2230ffb07550SAl Viro kmsg->msg_namelen = msg.msg_namelen; 2231ffb07550SAl Viro if (!msg.msg_name) 22326a2a2b3aSAni Sinha kmsg->msg_namelen = 0; 22336a2a2b3aSAni Sinha 2234dbb490b9SMatthew Leach if (kmsg->msg_namelen < 0) 2235dbb490b9SMatthew Leach return -EINVAL; 2236dbb490b9SMatthew Leach 22371661bf36SDan Carpenter if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 2238db31c55aSDan Carpenter kmsg->msg_namelen = sizeof(struct sockaddr_storage); 223908adb7daSAl Viro 224008adb7daSAl Viro if (save_addr) 2241ffb07550SAl Viro *save_addr = msg.msg_name; 224208adb7daSAl Viro 2243ffb07550SAl Viro if (msg.msg_name && kmsg->msg_namelen) { 224408adb7daSAl Viro if (!save_addr) { 2245864d9664SPaolo Abeni err = move_addr_to_kernel(msg.msg_name, 2246864d9664SPaolo Abeni kmsg->msg_namelen, 224708adb7daSAl Viro kmsg->msg_name); 224808adb7daSAl Viro if (err < 0) 224908adb7daSAl Viro return err; 225008adb7daSAl Viro } 225108adb7daSAl Viro } else { 225208adb7daSAl Viro kmsg->msg_name = NULL; 225308adb7daSAl Viro kmsg->msg_namelen = 0; 225408adb7daSAl Viro } 225508adb7daSAl Viro 2256ffb07550SAl Viro if (msg.msg_iovlen > UIO_MAXIOV) 225708adb7daSAl Viro return -EMSGSIZE; 225808adb7daSAl Viro 22590345f931Stadeusz.struk@intel.com kmsg->msg_iocb = NULL; 22600345f931Stadeusz.struk@intel.com 226187e5e6daSJens Axboe err = import_iovec(save_addr ? READ : WRITE, 2262ffb07550SAl Viro msg.msg_iov, msg.msg_iovlen, 2263da184284SAl Viro UIO_FASTIOV, iov, &kmsg->msg_iter); 226487e5e6daSJens Axboe return err < 0 ? err : 0; 22651661bf36SDan Carpenter } 22661661bf36SDan Carpenter 22674257c8caSJens Axboe static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys, 22684257c8caSJens Axboe unsigned int flags, struct used_address *used_address, 226928a94d8fSTom Herbert unsigned int allowed_msghdr_flags) 22701da177e4SLinus Torvalds { 2271b9d717a7SAlex Williamson unsigned char ctl[sizeof(struct cmsghdr) + 20] 2272846cc123SAmit Kushwaha __aligned(sizeof(__kernel_size_t)); 2273b9d717a7SAlex Williamson /* 20 is size of ipv6_pktinfo */ 22741da177e4SLinus Torvalds unsigned char *ctl_buf = ctl; 2275d8725c86SAl Viro int ctl_len; 227608adb7daSAl Viro ssize_t err; 22771da177e4SLinus Torvalds 22781da177e4SLinus Torvalds err = -ENOBUFS; 22791da177e4SLinus Torvalds 2280228e548eSAnton Blanchard if (msg_sys->msg_controllen > INT_MAX) 22814257c8caSJens Axboe goto out; 228228a94d8fSTom Herbert flags |= (msg_sys->msg_flags & allowed_msghdr_flags); 2283228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 22841da177e4SLinus Torvalds if ((MSG_CMSG_COMPAT & flags) && ctl_len) { 228589bddce5SStephen Hemminger err = 2286228e548eSAnton Blanchard cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, 228789bddce5SStephen Hemminger sizeof(ctl)); 22881da177e4SLinus Torvalds if (err) 22894257c8caSJens Axboe goto out; 2290228e548eSAnton Blanchard ctl_buf = msg_sys->msg_control; 2291228e548eSAnton Blanchard ctl_len = msg_sys->msg_controllen; 22921da177e4SLinus Torvalds } else if (ctl_len) { 2293ac4340fcSDavid S. Miller BUILD_BUG_ON(sizeof(struct cmsghdr) != 2294ac4340fcSDavid S. Miller CMSG_ALIGN(sizeof(struct cmsghdr))); 229589bddce5SStephen Hemminger if (ctl_len > sizeof(ctl)) { 22961da177e4SLinus Torvalds ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); 22971da177e4SLinus Torvalds if (ctl_buf == NULL) 22984257c8caSJens Axboe goto out; 22991da177e4SLinus Torvalds } 23001da177e4SLinus Torvalds err = -EFAULT; 23011da177e4SLinus Torvalds /* 2302228e548eSAnton Blanchard * Careful! Before this, msg_sys->msg_control contains a user pointer. 23031da177e4SLinus Torvalds * Afterwards, it will be a kernel pointer. Thus the compiler-assisted 23041da177e4SLinus Torvalds * checking falls down on this. 23051da177e4SLinus Torvalds */ 2306fb8621bbSNamhyung Kim if (copy_from_user(ctl_buf, 2307228e548eSAnton Blanchard (void __user __force *)msg_sys->msg_control, 230889bddce5SStephen Hemminger ctl_len)) 23091da177e4SLinus Torvalds goto out_freectl; 2310228e548eSAnton Blanchard msg_sys->msg_control = ctl_buf; 23111da177e4SLinus Torvalds } 2312228e548eSAnton Blanchard msg_sys->msg_flags = flags; 23131da177e4SLinus Torvalds 23141da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 2315228e548eSAnton Blanchard msg_sys->msg_flags |= MSG_DONTWAIT; 2316c71d8ebeSTetsuo Handa /* 2317c71d8ebeSTetsuo Handa * If this is sendmmsg() and current destination address is same as 2318c71d8ebeSTetsuo Handa * previously succeeded address, omit asking LSM's decision. 2319c71d8ebeSTetsuo Handa * used_address->name_len is initialized to UINT_MAX so that the first 2320c71d8ebeSTetsuo Handa * destination address never matches. 2321c71d8ebeSTetsuo Handa */ 2322bc909d9dSMathieu Desnoyers if (used_address && msg_sys->msg_name && 2323bc909d9dSMathieu Desnoyers used_address->name_len == msg_sys->msg_namelen && 2324bc909d9dSMathieu Desnoyers !memcmp(&used_address->name, msg_sys->msg_name, 2325c71d8ebeSTetsuo Handa used_address->name_len)) { 2326d8725c86SAl Viro err = sock_sendmsg_nosec(sock, msg_sys); 2327c71d8ebeSTetsuo Handa goto out_freectl; 2328c71d8ebeSTetsuo Handa } 2329d8725c86SAl Viro err = sock_sendmsg(sock, msg_sys); 2330c71d8ebeSTetsuo Handa /* 2331c71d8ebeSTetsuo Handa * If this is sendmmsg() and sending to current destination address was 2332c71d8ebeSTetsuo Handa * successful, remember it. 2333c71d8ebeSTetsuo Handa */ 2334c71d8ebeSTetsuo Handa if (used_address && err >= 0) { 2335c71d8ebeSTetsuo Handa used_address->name_len = msg_sys->msg_namelen; 2336bc909d9dSMathieu Desnoyers if (msg_sys->msg_name) 2337bc909d9dSMathieu Desnoyers memcpy(&used_address->name, msg_sys->msg_name, 2338c71d8ebeSTetsuo Handa used_address->name_len); 2339c71d8ebeSTetsuo Handa } 23401da177e4SLinus Torvalds 23411da177e4SLinus Torvalds out_freectl: 23421da177e4SLinus Torvalds if (ctl_buf != ctl) 23431da177e4SLinus Torvalds sock_kfree_s(sock->sk, ctl_buf, ctl_len); 23444257c8caSJens Axboe out: 23454257c8caSJens Axboe return err; 23464257c8caSJens Axboe } 23474257c8caSJens Axboe 23484257c8caSJens Axboe static int sendmsg_copy_msghdr(struct msghdr *msg, 23494257c8caSJens Axboe struct user_msghdr __user *umsg, unsigned flags, 23504257c8caSJens Axboe struct iovec **iov) 23514257c8caSJens Axboe { 23524257c8caSJens Axboe int err; 23534257c8caSJens Axboe 23544257c8caSJens Axboe if (flags & MSG_CMSG_COMPAT) { 23554257c8caSJens Axboe struct compat_msghdr __user *msg_compat; 23564257c8caSJens Axboe 23574257c8caSJens Axboe msg_compat = (struct compat_msghdr __user *) umsg; 23584257c8caSJens Axboe err = get_compat_msghdr(msg, msg_compat, NULL, iov); 23594257c8caSJens Axboe } else { 23604257c8caSJens Axboe err = copy_msghdr_from_user(msg, umsg, NULL, iov); 23614257c8caSJens Axboe } 23624257c8caSJens Axboe if (err < 0) 23634257c8caSJens Axboe return err; 23644257c8caSJens Axboe 23654257c8caSJens Axboe return 0; 23664257c8caSJens Axboe } 23674257c8caSJens Axboe 23684257c8caSJens Axboe static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, 23694257c8caSJens Axboe struct msghdr *msg_sys, unsigned int flags, 23704257c8caSJens Axboe struct used_address *used_address, 23714257c8caSJens Axboe unsigned int allowed_msghdr_flags) 23724257c8caSJens Axboe { 23734257c8caSJens Axboe struct sockaddr_storage address; 23744257c8caSJens Axboe struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 23754257c8caSJens Axboe ssize_t err; 23764257c8caSJens Axboe 23774257c8caSJens Axboe msg_sys->msg_name = &address; 23784257c8caSJens Axboe 23794257c8caSJens Axboe err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov); 23804257c8caSJens Axboe if (err < 0) 23814257c8caSJens Axboe return err; 23824257c8caSJens Axboe 23834257c8caSJens Axboe err = ____sys_sendmsg(sock, msg_sys, flags, used_address, 23844257c8caSJens Axboe allowed_msghdr_flags); 2385a74e9106SEric Dumazet kfree(iov); 2386228e548eSAnton Blanchard return err; 2387228e548eSAnton Blanchard } 2388228e548eSAnton Blanchard 2389228e548eSAnton Blanchard /* 2390228e548eSAnton Blanchard * BSD sendmsg interface 2391228e548eSAnton Blanchard */ 23920fa03c62SJens Axboe long __sys_sendmsg_sock(struct socket *sock, struct user_msghdr __user *msg, 23930fa03c62SJens Axboe unsigned int flags) 23940fa03c62SJens Axboe { 23950fa03c62SJens Axboe struct msghdr msg_sys; 23960fa03c62SJens Axboe 23970fa03c62SJens Axboe return ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0); 23980fa03c62SJens Axboe } 2399228e548eSAnton Blanchard 2400e1834a32SDominik Brodowski long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, 2401e1834a32SDominik Brodowski bool forbid_cmsg_compat) 2402228e548eSAnton Blanchard { 2403228e548eSAnton Blanchard int fput_needed, err; 2404228e548eSAnton Blanchard struct msghdr msg_sys; 24051be374a0SAndy Lutomirski struct socket *sock; 2406228e548eSAnton Blanchard 2407e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT)) 2408e1834a32SDominik Brodowski return -EINVAL; 2409e1834a32SDominik Brodowski 24101be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2411228e548eSAnton Blanchard if (!sock) 2412228e548eSAnton Blanchard goto out; 2413228e548eSAnton Blanchard 241428a94d8fSTom Herbert err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0); 2415228e548eSAnton Blanchard 24166cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 24171da177e4SLinus Torvalds out: 24181da177e4SLinus Torvalds return err; 24191da177e4SLinus Torvalds } 24201da177e4SLinus Torvalds 2421666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags) 2422a7526eb5SAndy Lutomirski { 2423e1834a32SDominik Brodowski return __sys_sendmsg(fd, msg, flags, true); 2424a7526eb5SAndy Lutomirski } 2425a7526eb5SAndy Lutomirski 2426228e548eSAnton Blanchard /* 2427228e548eSAnton Blanchard * Linux sendmmsg interface 2428228e548eSAnton Blanchard */ 2429228e548eSAnton Blanchard 2430228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 2431e1834a32SDominik Brodowski unsigned int flags, bool forbid_cmsg_compat) 2432228e548eSAnton Blanchard { 2433228e548eSAnton Blanchard int fput_needed, err, datagrams; 2434228e548eSAnton Blanchard struct socket *sock; 2435228e548eSAnton Blanchard struct mmsghdr __user *entry; 2436228e548eSAnton Blanchard struct compat_mmsghdr __user *compat_entry; 2437228e548eSAnton Blanchard struct msghdr msg_sys; 2438c71d8ebeSTetsuo Handa struct used_address used_address; 2439f092276dSTom Herbert unsigned int oflags = flags; 2440228e548eSAnton Blanchard 2441e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT)) 2442e1834a32SDominik Brodowski return -EINVAL; 2443e1834a32SDominik Brodowski 244498382f41SAnton Blanchard if (vlen > UIO_MAXIOV) 244598382f41SAnton Blanchard vlen = UIO_MAXIOV; 2446228e548eSAnton Blanchard 2447228e548eSAnton Blanchard datagrams = 0; 2448228e548eSAnton Blanchard 2449228e548eSAnton Blanchard sock = sockfd_lookup_light(fd, &err, &fput_needed); 2450228e548eSAnton Blanchard if (!sock) 2451228e548eSAnton Blanchard return err; 2452228e548eSAnton Blanchard 2453c71d8ebeSTetsuo Handa used_address.name_len = UINT_MAX; 2454228e548eSAnton Blanchard entry = mmsg; 2455228e548eSAnton Blanchard compat_entry = (struct compat_mmsghdr __user *)mmsg; 2456728ffb86SAnton Blanchard err = 0; 2457f092276dSTom Herbert flags |= MSG_BATCH; 2458228e548eSAnton Blanchard 2459228e548eSAnton Blanchard while (datagrams < vlen) { 2460f092276dSTom Herbert if (datagrams == vlen - 1) 2461f092276dSTom Herbert flags = oflags; 2462f092276dSTom Herbert 2463228e548eSAnton Blanchard if (MSG_CMSG_COMPAT & flags) { 2464666547ffSAl Viro err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry, 246528a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2466228e548eSAnton Blanchard if (err < 0) 2467228e548eSAnton Blanchard break; 2468228e548eSAnton Blanchard err = __put_user(err, &compat_entry->msg_len); 2469228e548eSAnton Blanchard ++compat_entry; 2470228e548eSAnton Blanchard } else { 2471a7526eb5SAndy Lutomirski err = ___sys_sendmsg(sock, 2472666547ffSAl Viro (struct user_msghdr __user *)entry, 247328a94d8fSTom Herbert &msg_sys, flags, &used_address, MSG_EOR); 2474228e548eSAnton Blanchard if (err < 0) 2475228e548eSAnton Blanchard break; 2476228e548eSAnton Blanchard err = put_user(err, &entry->msg_len); 2477228e548eSAnton Blanchard ++entry; 2478228e548eSAnton Blanchard } 2479228e548eSAnton Blanchard 2480228e548eSAnton Blanchard if (err) 2481228e548eSAnton Blanchard break; 2482228e548eSAnton Blanchard ++datagrams; 24833023898bSSoheil Hassas Yeganeh if (msg_data_left(&msg_sys)) 24843023898bSSoheil Hassas Yeganeh break; 2485a78cb84cSEric Dumazet cond_resched(); 2486228e548eSAnton Blanchard } 2487228e548eSAnton Blanchard 2488228e548eSAnton Blanchard fput_light(sock->file, fput_needed); 2489228e548eSAnton Blanchard 2490728ffb86SAnton Blanchard /* We only return an error if no datagrams were able to be sent */ 2491728ffb86SAnton Blanchard if (datagrams != 0) 2492228e548eSAnton Blanchard return datagrams; 2493228e548eSAnton Blanchard 2494228e548eSAnton Blanchard return err; 2495228e548eSAnton Blanchard } 2496228e548eSAnton Blanchard 2497228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, 2498228e548eSAnton Blanchard unsigned int, vlen, unsigned int, flags) 2499228e548eSAnton Blanchard { 2500e1834a32SDominik Brodowski return __sys_sendmmsg(fd, mmsg, vlen, flags, true); 2501228e548eSAnton Blanchard } 2502228e548eSAnton Blanchard 25034257c8caSJens Axboe static int recvmsg_copy_msghdr(struct msghdr *msg, 25044257c8caSJens Axboe struct user_msghdr __user *umsg, unsigned flags, 25054257c8caSJens Axboe struct sockaddr __user **uaddr, 25064257c8caSJens Axboe struct iovec **iov) 25074257c8caSJens Axboe { 25084257c8caSJens Axboe ssize_t err; 25094257c8caSJens Axboe 25104257c8caSJens Axboe if (MSG_CMSG_COMPAT & flags) { 25114257c8caSJens Axboe struct compat_msghdr __user *msg_compat; 25124257c8caSJens Axboe 25134257c8caSJens Axboe msg_compat = (struct compat_msghdr __user *) umsg; 25144257c8caSJens Axboe err = get_compat_msghdr(msg, msg_compat, uaddr, iov); 25154257c8caSJens Axboe } else { 25164257c8caSJens Axboe err = copy_msghdr_from_user(msg, umsg, uaddr, iov); 25174257c8caSJens Axboe } 25184257c8caSJens Axboe if (err < 0) 25194257c8caSJens Axboe return err; 25204257c8caSJens Axboe 25214257c8caSJens Axboe return 0; 25224257c8caSJens Axboe } 25234257c8caSJens Axboe 25244257c8caSJens Axboe static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys, 25254257c8caSJens Axboe struct user_msghdr __user *msg, 25264257c8caSJens Axboe struct sockaddr __user *uaddr, 25274257c8caSJens Axboe unsigned int flags, int nosec) 25281da177e4SLinus Torvalds { 252989bddce5SStephen Hemminger struct compat_msghdr __user *msg_compat = 253089bddce5SStephen Hemminger (struct compat_msghdr __user *) msg; 25314257c8caSJens Axboe int __user *uaddr_len = COMPAT_NAMELEN(msg); 25324257c8caSJens Axboe struct sockaddr_storage addr; 25331da177e4SLinus Torvalds unsigned long cmsg_ptr; 25342da62906SAl Viro int len; 253508adb7daSAl Viro ssize_t err; 25361da177e4SLinus Torvalds 253708adb7daSAl Viro msg_sys->msg_name = &addr; 2538a2e27255SArnaldo Carvalho de Melo cmsg_ptr = (unsigned long)msg_sys->msg_control; 2539a2e27255SArnaldo Carvalho de Melo msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 25401da177e4SLinus Torvalds 2541f3d33426SHannes Frederic Sowa /* We assume all kernel code knows the size of sockaddr_storage */ 2542f3d33426SHannes Frederic Sowa msg_sys->msg_namelen = 0; 2543f3d33426SHannes Frederic Sowa 25441da177e4SLinus Torvalds if (sock->file->f_flags & O_NONBLOCK) 25451da177e4SLinus Torvalds flags |= MSG_DONTWAIT; 25462da62906SAl Viro err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags); 25471da177e4SLinus Torvalds if (err < 0) 25484257c8caSJens Axboe goto out; 25491da177e4SLinus Torvalds len = err; 25501da177e4SLinus Torvalds 25511da177e4SLinus Torvalds if (uaddr != NULL) { 255243db362dSMaciej Żenczykowski err = move_addr_to_user(&addr, 2553a2e27255SArnaldo Carvalho de Melo msg_sys->msg_namelen, uaddr, 255489bddce5SStephen Hemminger uaddr_len); 25551da177e4SLinus Torvalds if (err < 0) 25564257c8caSJens Axboe goto out; 25571da177e4SLinus Torvalds } 2558a2e27255SArnaldo Carvalho de Melo err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT), 255937f7f421SDavid S. Miller COMPAT_FLAGS(msg)); 25601da177e4SLinus Torvalds if (err) 25614257c8caSJens Axboe goto out; 25621da177e4SLinus Torvalds if (MSG_CMSG_COMPAT & flags) 2563a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 25641da177e4SLinus Torvalds &msg_compat->msg_controllen); 25651da177e4SLinus Torvalds else 2566a2e27255SArnaldo Carvalho de Melo err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr, 25671da177e4SLinus Torvalds &msg->msg_controllen); 25681da177e4SLinus Torvalds if (err) 25694257c8caSJens Axboe goto out; 25701da177e4SLinus Torvalds err = len; 25714257c8caSJens Axboe out: 25724257c8caSJens Axboe return err; 25734257c8caSJens Axboe } 25741da177e4SLinus Torvalds 25754257c8caSJens Axboe static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, 25764257c8caSJens Axboe struct msghdr *msg_sys, unsigned int flags, int nosec) 25774257c8caSJens Axboe { 25784257c8caSJens Axboe struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 25794257c8caSJens Axboe /* user mode address pointers */ 25804257c8caSJens Axboe struct sockaddr __user *uaddr; 25814257c8caSJens Axboe ssize_t err; 25824257c8caSJens Axboe 25834257c8caSJens Axboe err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov); 25844257c8caSJens Axboe if (err < 0) 25854257c8caSJens Axboe return err; 25864257c8caSJens Axboe 25874257c8caSJens Axboe err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec); 2588a74e9106SEric Dumazet kfree(iov); 2589a2e27255SArnaldo Carvalho de Melo return err; 2590a2e27255SArnaldo Carvalho de Melo } 2591a2e27255SArnaldo Carvalho de Melo 2592a2e27255SArnaldo Carvalho de Melo /* 2593a2e27255SArnaldo Carvalho de Melo * BSD recvmsg interface 2594a2e27255SArnaldo Carvalho de Melo */ 2595a2e27255SArnaldo Carvalho de Melo 2596aa1fa28fSJens Axboe long __sys_recvmsg_sock(struct socket *sock, struct user_msghdr __user *msg, 2597aa1fa28fSJens Axboe unsigned int flags) 2598aa1fa28fSJens Axboe { 2599aa1fa28fSJens Axboe struct msghdr msg_sys; 2600aa1fa28fSJens Axboe 2601aa1fa28fSJens Axboe return ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2602aa1fa28fSJens Axboe } 2603aa1fa28fSJens Axboe 2604e1834a32SDominik Brodowski long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, 2605e1834a32SDominik Brodowski bool forbid_cmsg_compat) 2606a2e27255SArnaldo Carvalho de Melo { 2607a2e27255SArnaldo Carvalho de Melo int fput_needed, err; 2608a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 26091be374a0SAndy Lutomirski struct socket *sock; 2610a2e27255SArnaldo Carvalho de Melo 2611e1834a32SDominik Brodowski if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT)) 2612e1834a32SDominik Brodowski return -EINVAL; 2613e1834a32SDominik Brodowski 26141be374a0SAndy Lutomirski sock = sockfd_lookup_light(fd, &err, &fput_needed); 2615a2e27255SArnaldo Carvalho de Melo if (!sock) 2616a2e27255SArnaldo Carvalho de Melo goto out; 2617a2e27255SArnaldo Carvalho de Melo 2618a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2619a2e27255SArnaldo Carvalho de Melo 26206cb153caSBenjamin LaHaise fput_light(sock->file, fput_needed); 26211da177e4SLinus Torvalds out: 26221da177e4SLinus Torvalds return err; 26231da177e4SLinus Torvalds } 26241da177e4SLinus Torvalds 2625666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg, 2626a7526eb5SAndy Lutomirski unsigned int, flags) 2627a7526eb5SAndy Lutomirski { 2628e1834a32SDominik Brodowski return __sys_recvmsg(fd, msg, flags, true); 2629a7526eb5SAndy Lutomirski } 2630a7526eb5SAndy Lutomirski 2631a2e27255SArnaldo Carvalho de Melo /* 2632a2e27255SArnaldo Carvalho de Melo * Linux recvmmsg interface 2633a2e27255SArnaldo Carvalho de Melo */ 26341da177e4SLinus Torvalds 2635e11d4284SArnd Bergmann static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg, 2636e11d4284SArnd Bergmann unsigned int vlen, unsigned int flags, 2637e11d4284SArnd Bergmann struct timespec64 *timeout) 2638a2e27255SArnaldo Carvalho de Melo { 2639a2e27255SArnaldo Carvalho de Melo int fput_needed, err, datagrams; 2640a2e27255SArnaldo Carvalho de Melo struct socket *sock; 2641a2e27255SArnaldo Carvalho de Melo struct mmsghdr __user *entry; 2642d7256d0eSJean-Mickael Guerin struct compat_mmsghdr __user *compat_entry; 2643a2e27255SArnaldo Carvalho de Melo struct msghdr msg_sys; 2644766b9f92SDeepa Dinamani struct timespec64 end_time; 2645766b9f92SDeepa Dinamani struct timespec64 timeout64; 2646a2e27255SArnaldo Carvalho de Melo 2647a2e27255SArnaldo Carvalho de Melo if (timeout && 2648a2e27255SArnaldo Carvalho de Melo poll_select_set_timeout(&end_time, timeout->tv_sec, 2649a2e27255SArnaldo Carvalho de Melo timeout->tv_nsec)) 2650a2e27255SArnaldo Carvalho de Melo return -EINVAL; 2651a2e27255SArnaldo Carvalho de Melo 2652a2e27255SArnaldo Carvalho de Melo datagrams = 0; 2653a2e27255SArnaldo Carvalho de Melo 2654a2e27255SArnaldo Carvalho de Melo sock = sockfd_lookup_light(fd, &err, &fput_needed); 2655a2e27255SArnaldo Carvalho de Melo if (!sock) 2656a2e27255SArnaldo Carvalho de Melo return err; 2657a2e27255SArnaldo Carvalho de Melo 26587797dc41SSoheil Hassas Yeganeh if (likely(!(flags & MSG_ERRQUEUE))) { 2659a2e27255SArnaldo Carvalho de Melo err = sock_error(sock->sk); 2660e623a9e9SMaxime Jayat if (err) { 2661e623a9e9SMaxime Jayat datagrams = err; 2662a2e27255SArnaldo Carvalho de Melo goto out_put; 2663e623a9e9SMaxime Jayat } 26647797dc41SSoheil Hassas Yeganeh } 2665a2e27255SArnaldo Carvalho de Melo 2666a2e27255SArnaldo Carvalho de Melo entry = mmsg; 2667d7256d0eSJean-Mickael Guerin compat_entry = (struct compat_mmsghdr __user *)mmsg; 2668a2e27255SArnaldo Carvalho de Melo 2669a2e27255SArnaldo Carvalho de Melo while (datagrams < vlen) { 2670a2e27255SArnaldo Carvalho de Melo /* 2671a2e27255SArnaldo Carvalho de Melo * No need to ask LSM for more than the first datagram. 2672a2e27255SArnaldo Carvalho de Melo */ 2673d7256d0eSJean-Mickael Guerin if (MSG_CMSG_COMPAT & flags) { 2674666547ffSAl Viro err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry, 2675b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2676b9eb8b87SAnton Blanchard datagrams); 2677d7256d0eSJean-Mickael Guerin if (err < 0) 2678d7256d0eSJean-Mickael Guerin break; 2679d7256d0eSJean-Mickael Guerin err = __put_user(err, &compat_entry->msg_len); 2680d7256d0eSJean-Mickael Guerin ++compat_entry; 2681d7256d0eSJean-Mickael Guerin } else { 2682a7526eb5SAndy Lutomirski err = ___sys_recvmsg(sock, 2683666547ffSAl Viro (struct user_msghdr __user *)entry, 2684b9eb8b87SAnton Blanchard &msg_sys, flags & ~MSG_WAITFORONE, 2685b9eb8b87SAnton Blanchard datagrams); 2686a2e27255SArnaldo Carvalho de Melo if (err < 0) 2687a2e27255SArnaldo Carvalho de Melo break; 2688a2e27255SArnaldo Carvalho de Melo err = put_user(err, &entry->msg_len); 2689d7256d0eSJean-Mickael Guerin ++entry; 2690d7256d0eSJean-Mickael Guerin } 2691d7256d0eSJean-Mickael Guerin 2692a2e27255SArnaldo Carvalho de Melo if (err) 2693a2e27255SArnaldo Carvalho de Melo break; 2694a2e27255SArnaldo Carvalho de Melo ++datagrams; 2695a2e27255SArnaldo Carvalho de Melo 269671c5c159SBrandon L Black /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ 269771c5c159SBrandon L Black if (flags & MSG_WAITFORONE) 269871c5c159SBrandon L Black flags |= MSG_DONTWAIT; 269971c5c159SBrandon L Black 2700a2e27255SArnaldo Carvalho de Melo if (timeout) { 2701766b9f92SDeepa Dinamani ktime_get_ts64(&timeout64); 2702c2e6c856SArnd Bergmann *timeout = timespec64_sub(end_time, timeout64); 2703a2e27255SArnaldo Carvalho de Melo if (timeout->tv_sec < 0) { 2704a2e27255SArnaldo Carvalho de Melo timeout->tv_sec = timeout->tv_nsec = 0; 2705a2e27255SArnaldo Carvalho de Melo break; 2706a2e27255SArnaldo Carvalho de Melo } 2707a2e27255SArnaldo Carvalho de Melo 2708a2e27255SArnaldo Carvalho de Melo /* Timeout, return less than vlen datagrams */ 2709a2e27255SArnaldo Carvalho de Melo if (timeout->tv_nsec == 0 && timeout->tv_sec == 0) 2710a2e27255SArnaldo Carvalho de Melo break; 2711a2e27255SArnaldo Carvalho de Melo } 2712a2e27255SArnaldo Carvalho de Melo 2713a2e27255SArnaldo Carvalho de Melo /* Out of band data, return right away */ 2714a2e27255SArnaldo Carvalho de Melo if (msg_sys.msg_flags & MSG_OOB) 2715a2e27255SArnaldo Carvalho de Melo break; 2716a78cb84cSEric Dumazet cond_resched(); 2717a2e27255SArnaldo Carvalho de Melo } 2718a2e27255SArnaldo Carvalho de Melo 2719a2e27255SArnaldo Carvalho de Melo if (err == 0) 272034b88a68SArnaldo Carvalho de Melo goto out_put; 2721a2e27255SArnaldo Carvalho de Melo 272234b88a68SArnaldo Carvalho de Melo if (datagrams == 0) { 272334b88a68SArnaldo Carvalho de Melo datagrams = err; 272434b88a68SArnaldo Carvalho de Melo goto out_put; 272534b88a68SArnaldo Carvalho de Melo } 272634b88a68SArnaldo Carvalho de Melo 2727a2e27255SArnaldo Carvalho de Melo /* 2728a2e27255SArnaldo Carvalho de Melo * We may return less entries than requested (vlen) if the 2729a2e27255SArnaldo Carvalho de Melo * sock is non block and there aren't enough datagrams... 2730a2e27255SArnaldo Carvalho de Melo */ 2731a2e27255SArnaldo Carvalho de Melo if (err != -EAGAIN) { 2732a2e27255SArnaldo Carvalho de Melo /* 2733a2e27255SArnaldo Carvalho de Melo * ... or if recvmsg returns an error after we 2734a2e27255SArnaldo Carvalho de Melo * received some datagrams, where we record the 2735a2e27255SArnaldo Carvalho de Melo * error to return on the next call or if the 2736a2e27255SArnaldo Carvalho de Melo * app asks about it using getsockopt(SO_ERROR). 2737a2e27255SArnaldo Carvalho de Melo */ 2738a2e27255SArnaldo Carvalho de Melo sock->sk->sk_err = -err; 2739a2e27255SArnaldo Carvalho de Melo } 274034b88a68SArnaldo Carvalho de Melo out_put: 274134b88a68SArnaldo Carvalho de Melo fput_light(sock->file, fput_needed); 2742a2e27255SArnaldo Carvalho de Melo 2743a2e27255SArnaldo Carvalho de Melo return datagrams; 2744a2e27255SArnaldo Carvalho de Melo } 2745a2e27255SArnaldo Carvalho de Melo 2746e11d4284SArnd Bergmann int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, 27471255e269SDominik Brodowski unsigned int vlen, unsigned int flags, 2748e11d4284SArnd Bergmann struct __kernel_timespec __user *timeout, 2749e11d4284SArnd Bergmann struct old_timespec32 __user *timeout32) 2750a2e27255SArnaldo Carvalho de Melo { 2751a2e27255SArnaldo Carvalho de Melo int datagrams; 2752c2e6c856SArnd Bergmann struct timespec64 timeout_sys; 2753a2e27255SArnaldo Carvalho de Melo 2754e11d4284SArnd Bergmann if (timeout && get_timespec64(&timeout_sys, timeout)) 2755a2e27255SArnaldo Carvalho de Melo return -EFAULT; 2756a2e27255SArnaldo Carvalho de Melo 2757e11d4284SArnd Bergmann if (timeout32 && get_old_timespec32(&timeout_sys, timeout32)) 2758e11d4284SArnd Bergmann return -EFAULT; 2759a2e27255SArnaldo Carvalho de Melo 2760e11d4284SArnd Bergmann if (!timeout && !timeout32) 2761e11d4284SArnd Bergmann return do_recvmmsg(fd, mmsg, vlen, flags, NULL); 2762e11d4284SArnd Bergmann 2763e11d4284SArnd Bergmann datagrams = do_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys); 2764e11d4284SArnd Bergmann 2765e11d4284SArnd Bergmann if (datagrams <= 0) 2766e11d4284SArnd Bergmann return datagrams; 2767e11d4284SArnd Bergmann 2768e11d4284SArnd Bergmann if (timeout && put_timespec64(&timeout_sys, timeout)) 2769e11d4284SArnd Bergmann datagrams = -EFAULT; 2770e11d4284SArnd Bergmann 2771e11d4284SArnd Bergmann if (timeout32 && put_old_timespec32(&timeout_sys, timeout32)) 2772a2e27255SArnaldo Carvalho de Melo datagrams = -EFAULT; 2773a2e27255SArnaldo Carvalho de Melo 2774a2e27255SArnaldo Carvalho de Melo return datagrams; 2775a2e27255SArnaldo Carvalho de Melo } 2776a2e27255SArnaldo Carvalho de Melo 27771255e269SDominik Brodowski SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, 27781255e269SDominik Brodowski unsigned int, vlen, unsigned int, flags, 2779c2e6c856SArnd Bergmann struct __kernel_timespec __user *, timeout) 27801255e269SDominik Brodowski { 2781e11d4284SArnd Bergmann if (flags & MSG_CMSG_COMPAT) 2782e11d4284SArnd Bergmann return -EINVAL; 2783e11d4284SArnd Bergmann 2784e11d4284SArnd Bergmann return __sys_recvmmsg(fd, mmsg, vlen, flags, timeout, NULL); 27851255e269SDominik Brodowski } 27861255e269SDominik Brodowski 2787e11d4284SArnd Bergmann #ifdef CONFIG_COMPAT_32BIT_TIME 2788e11d4284SArnd Bergmann SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct mmsghdr __user *, mmsg, 2789e11d4284SArnd Bergmann unsigned int, vlen, unsigned int, flags, 2790e11d4284SArnd Bergmann struct old_timespec32 __user *, timeout) 2791e11d4284SArnd Bergmann { 2792e11d4284SArnd Bergmann if (flags & MSG_CMSG_COMPAT) 2793e11d4284SArnd Bergmann return -EINVAL; 2794e11d4284SArnd Bergmann 2795e11d4284SArnd Bergmann return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL, timeout); 2796e11d4284SArnd Bergmann } 2797e11d4284SArnd Bergmann #endif 2798e11d4284SArnd Bergmann 2799a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL 28001da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */ 28011da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long)) 2802228e548eSAnton Blanchard static const unsigned char nargs[21] = { 280389bddce5SStephen Hemminger AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 28041da177e4SLinus Torvalds AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 2805aaca0bdcSUlrich Drepper AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 2806228e548eSAnton Blanchard AL(4), AL(5), AL(4) 280789bddce5SStephen Hemminger }; 280889bddce5SStephen Hemminger 28091da177e4SLinus Torvalds #undef AL 28101da177e4SLinus Torvalds 28111da177e4SLinus Torvalds /* 28121da177e4SLinus Torvalds * System call vectors. 28131da177e4SLinus Torvalds * 28141da177e4SLinus Torvalds * Argument checking cleaned up. Saved 20% in size. 28151da177e4SLinus Torvalds * This function doesn't need to set the kernel lock because 28161da177e4SLinus Torvalds * it is set by the callees. 28171da177e4SLinus Torvalds */ 28181da177e4SLinus Torvalds 28193e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) 28201da177e4SLinus Torvalds { 28212950fa9dSChen Gang unsigned long a[AUDITSC_ARGS]; 28221da177e4SLinus Torvalds unsigned long a0, a1; 28231da177e4SLinus Torvalds int err; 282447379052SArjan van de Ven unsigned int len; 28251da177e4SLinus Torvalds 2826228e548eSAnton Blanchard if (call < 1 || call > SYS_SENDMMSG) 28271da177e4SLinus Torvalds return -EINVAL; 2828c8e8cd57SJeremy Cline call = array_index_nospec(call, SYS_SENDMMSG + 1); 28291da177e4SLinus Torvalds 283047379052SArjan van de Ven len = nargs[call]; 283147379052SArjan van de Ven if (len > sizeof(a)) 283247379052SArjan van de Ven return -EINVAL; 283347379052SArjan van de Ven 28341da177e4SLinus Torvalds /* copy_from_user should be SMP safe. */ 283547379052SArjan van de Ven if (copy_from_user(a, args, len)) 28361da177e4SLinus Torvalds return -EFAULT; 28371da177e4SLinus Torvalds 28382950fa9dSChen Gang err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); 28392950fa9dSChen Gang if (err) 28402950fa9dSChen Gang return err; 28413ec3b2fbSDavid Woodhouse 28421da177e4SLinus Torvalds a0 = a[0]; 28431da177e4SLinus Torvalds a1 = a[1]; 28441da177e4SLinus Torvalds 284589bddce5SStephen Hemminger switch (call) { 28461da177e4SLinus Torvalds case SYS_SOCKET: 28479d6a15c3SDominik Brodowski err = __sys_socket(a0, a1, a[2]); 28481da177e4SLinus Torvalds break; 28491da177e4SLinus Torvalds case SYS_BIND: 2850a87d35d8SDominik Brodowski err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]); 28511da177e4SLinus Torvalds break; 28521da177e4SLinus Torvalds case SYS_CONNECT: 28531387c2c2SDominik Brodowski err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]); 28541da177e4SLinus Torvalds break; 28551da177e4SLinus Torvalds case SYS_LISTEN: 285625e290eeSDominik Brodowski err = __sys_listen(a0, a1); 28571da177e4SLinus Torvalds break; 28581da177e4SLinus Torvalds case SYS_ACCEPT: 28594541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1, 2860aaca0bdcSUlrich Drepper (int __user *)a[2], 0); 28611da177e4SLinus Torvalds break; 28621da177e4SLinus Torvalds case SYS_GETSOCKNAME: 286389bddce5SStephen Hemminger err = 28648882a107SDominik Brodowski __sys_getsockname(a0, (struct sockaddr __user *)a1, 286589bddce5SStephen Hemminger (int __user *)a[2]); 28661da177e4SLinus Torvalds break; 28671da177e4SLinus Torvalds case SYS_GETPEERNAME: 286889bddce5SStephen Hemminger err = 2869b21c8f83SDominik Brodowski __sys_getpeername(a0, (struct sockaddr __user *)a1, 287089bddce5SStephen Hemminger (int __user *)a[2]); 28711da177e4SLinus Torvalds break; 28721da177e4SLinus Torvalds case SYS_SOCKETPAIR: 28736debc8d8SDominik Brodowski err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]); 28741da177e4SLinus Torvalds break; 28751da177e4SLinus Torvalds case SYS_SEND: 2876f3bf896bSDominik Brodowski err = __sys_sendto(a0, (void __user *)a1, a[2], a[3], 2877f3bf896bSDominik Brodowski NULL, 0); 28781da177e4SLinus Torvalds break; 28791da177e4SLinus Torvalds case SYS_SENDTO: 2880211b634bSDominik Brodowski err = __sys_sendto(a0, (void __user *)a1, a[2], a[3], 28811da177e4SLinus Torvalds (struct sockaddr __user *)a[4], a[5]); 28821da177e4SLinus Torvalds break; 28831da177e4SLinus Torvalds case SYS_RECV: 2884d27e9afcSDominik Brodowski err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 2885d27e9afcSDominik Brodowski NULL, NULL); 28861da177e4SLinus Torvalds break; 28871da177e4SLinus Torvalds case SYS_RECVFROM: 28887a09e1ebSDominik Brodowski err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3], 288989bddce5SStephen Hemminger (struct sockaddr __user *)a[4], 289089bddce5SStephen Hemminger (int __user *)a[5]); 28911da177e4SLinus Torvalds break; 28921da177e4SLinus Torvalds case SYS_SHUTDOWN: 2893005a1aeaSDominik Brodowski err = __sys_shutdown(a0, a1); 28941da177e4SLinus Torvalds break; 28951da177e4SLinus Torvalds case SYS_SETSOCKOPT: 2896cc36dca0SDominik Brodowski err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3], 2897cc36dca0SDominik Brodowski a[4]); 28981da177e4SLinus Torvalds break; 28991da177e4SLinus Torvalds case SYS_GETSOCKOPT: 290089bddce5SStephen Hemminger err = 290113a2d70eSDominik Brodowski __sys_getsockopt(a0, a1, a[2], (char __user *)a[3], 290289bddce5SStephen Hemminger (int __user *)a[4]); 29031da177e4SLinus Torvalds break; 29041da177e4SLinus Torvalds case SYS_SENDMSG: 2905e1834a32SDominik Brodowski err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1, 2906e1834a32SDominik Brodowski a[2], true); 29071da177e4SLinus Torvalds break; 2908228e548eSAnton Blanchard case SYS_SENDMMSG: 2909e1834a32SDominik Brodowski err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], 2910e1834a32SDominik Brodowski a[3], true); 2911228e548eSAnton Blanchard break; 29121da177e4SLinus Torvalds case SYS_RECVMSG: 2913e1834a32SDominik Brodowski err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1, 2914e1834a32SDominik Brodowski a[2], true); 29151da177e4SLinus Torvalds break; 2916a2e27255SArnaldo Carvalho de Melo case SYS_RECVMMSG: 2917e11d4284SArnd Bergmann if (IS_ENABLED(CONFIG_64BIT) || !IS_ENABLED(CONFIG_64BIT_TIME)) 2918e11d4284SArnd Bergmann err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1, 2919e11d4284SArnd Bergmann a[2], a[3], 2920e11d4284SArnd Bergmann (struct __kernel_timespec __user *)a[4], 2921e11d4284SArnd Bergmann NULL); 2922e11d4284SArnd Bergmann else 2923e11d4284SArnd Bergmann err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1, 2924e11d4284SArnd Bergmann a[2], a[3], NULL, 2925e11d4284SArnd Bergmann (struct old_timespec32 __user *)a[4]); 2926a2e27255SArnaldo Carvalho de Melo break; 2927de11defeSUlrich Drepper case SYS_ACCEPT4: 29284541e805SDominik Brodowski err = __sys_accept4(a0, (struct sockaddr __user *)a1, 2929de11defeSUlrich Drepper (int __user *)a[2], a[3]); 2930aaca0bdcSUlrich Drepper break; 29311da177e4SLinus Torvalds default: 29321da177e4SLinus Torvalds err = -EINVAL; 29331da177e4SLinus Torvalds break; 29341da177e4SLinus Torvalds } 29351da177e4SLinus Torvalds return err; 29361da177e4SLinus Torvalds } 29371da177e4SLinus Torvalds 29381da177e4SLinus Torvalds #endif /* __ARCH_WANT_SYS_SOCKETCALL */ 29391da177e4SLinus Torvalds 294055737fdaSStephen Hemminger /** 294155737fdaSStephen Hemminger * sock_register - add a socket protocol handler 294255737fdaSStephen Hemminger * @ops: description of protocol 294355737fdaSStephen Hemminger * 29441da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 29451da177e4SLinus Torvalds * advertise its address family, and have it linked into the 2946e793c0f7SMasanari Iida * socket interface. The value ops->family corresponds to the 294755737fdaSStephen Hemminger * socket system call protocol family. 29481da177e4SLinus Torvalds */ 2949f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops) 29501da177e4SLinus Torvalds { 29511da177e4SLinus Torvalds int err; 29521da177e4SLinus Torvalds 29531da177e4SLinus Torvalds if (ops->family >= NPROTO) { 29543410f22eSYang Yingliang pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO); 29551da177e4SLinus Torvalds return -ENOBUFS; 29561da177e4SLinus Torvalds } 295755737fdaSStephen Hemminger 295855737fdaSStephen Hemminger spin_lock(&net_family_lock); 2959190683a9SEric Dumazet if (rcu_dereference_protected(net_families[ops->family], 2960190683a9SEric Dumazet lockdep_is_held(&net_family_lock))) 29611da177e4SLinus Torvalds err = -EEXIST; 296255737fdaSStephen Hemminger else { 2963cf778b00SEric Dumazet rcu_assign_pointer(net_families[ops->family], ops); 29641da177e4SLinus Torvalds err = 0; 29651da177e4SLinus Torvalds } 296655737fdaSStephen Hemminger spin_unlock(&net_family_lock); 296755737fdaSStephen Hemminger 29683410f22eSYang Yingliang pr_info("NET: Registered protocol family %d\n", ops->family); 29691da177e4SLinus Torvalds return err; 29701da177e4SLinus Torvalds } 2971c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register); 29721da177e4SLinus Torvalds 297355737fdaSStephen Hemminger /** 297455737fdaSStephen Hemminger * sock_unregister - remove a protocol handler 297555737fdaSStephen Hemminger * @family: protocol family to remove 297655737fdaSStephen Hemminger * 29771da177e4SLinus Torvalds * This function is called by a protocol handler that wants to 29781da177e4SLinus Torvalds * remove its address family, and have it unlinked from the 297955737fdaSStephen Hemminger * new socket creation. 298055737fdaSStephen Hemminger * 298155737fdaSStephen Hemminger * If protocol handler is a module, then it can use module reference 298255737fdaSStephen Hemminger * counts to protect against new references. If protocol handler is not 298355737fdaSStephen Hemminger * a module then it needs to provide its own protection in 298455737fdaSStephen Hemminger * the ops->create routine. 29851da177e4SLinus Torvalds */ 2986f0fd27d4SStephen Hemminger void sock_unregister(int family) 29871da177e4SLinus Torvalds { 2988f0fd27d4SStephen Hemminger BUG_ON(family < 0 || family >= NPROTO); 29891da177e4SLinus Torvalds 299055737fdaSStephen Hemminger spin_lock(&net_family_lock); 2991a9b3cd7fSStephen Hemminger RCU_INIT_POINTER(net_families[family], NULL); 299255737fdaSStephen Hemminger spin_unlock(&net_family_lock); 299355737fdaSStephen Hemminger 299455737fdaSStephen Hemminger synchronize_rcu(); 299555737fdaSStephen Hemminger 29963410f22eSYang Yingliang pr_info("NET: Unregistered protocol family %d\n", family); 29971da177e4SLinus Torvalds } 2998c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister); 29991da177e4SLinus Torvalds 3000bf2ae2e4SXin Long bool sock_is_registered(int family) 3001bf2ae2e4SXin Long { 300266b51b0aSJeremy Cline return family < NPROTO && rcu_access_pointer(net_families[family]); 3003bf2ae2e4SXin Long } 3004bf2ae2e4SXin Long 300577d76ea3SAndi Kleen static int __init sock_init(void) 30061da177e4SLinus Torvalds { 3007b3e19d92SNick Piggin int err; 30082ca794e5SEric W. Biederman /* 30092ca794e5SEric W. Biederman * Initialize the network sysctl infrastructure. 30102ca794e5SEric W. Biederman */ 30112ca794e5SEric W. Biederman err = net_sysctl_init(); 30122ca794e5SEric W. Biederman if (err) 30132ca794e5SEric W. Biederman goto out; 3014b3e19d92SNick Piggin 30151da177e4SLinus Torvalds /* 30161da177e4SLinus Torvalds * Initialize skbuff SLAB cache 30171da177e4SLinus Torvalds */ 30181da177e4SLinus Torvalds skb_init(); 30191da177e4SLinus Torvalds 30201da177e4SLinus Torvalds /* 30211da177e4SLinus Torvalds * Initialize the protocols module. 30221da177e4SLinus Torvalds */ 30231da177e4SLinus Torvalds 30241da177e4SLinus Torvalds init_inodecache(); 3025b3e19d92SNick Piggin 3026b3e19d92SNick Piggin err = register_filesystem(&sock_fs_type); 3027b3e19d92SNick Piggin if (err) 3028b3e19d92SNick Piggin goto out_fs; 30291da177e4SLinus Torvalds sock_mnt = kern_mount(&sock_fs_type); 3030b3e19d92SNick Piggin if (IS_ERR(sock_mnt)) { 3031b3e19d92SNick Piggin err = PTR_ERR(sock_mnt); 3032b3e19d92SNick Piggin goto out_mount; 3033b3e19d92SNick Piggin } 303477d76ea3SAndi Kleen 303577d76ea3SAndi Kleen /* The real protocol initialization is performed in later initcalls. 30361da177e4SLinus Torvalds */ 30371da177e4SLinus Torvalds 30381da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER 30396d11cfdbSPablo Neira Ayuso err = netfilter_init(); 30406d11cfdbSPablo Neira Ayuso if (err) 30416d11cfdbSPablo Neira Ayuso goto out; 30421da177e4SLinus Torvalds #endif 3043cbeb321aSDavid S. Miller 3044408eccceSDaniel Borkmann ptp_classifier_init(); 3045c1f19b51SRichard Cochran 3046b3e19d92SNick Piggin out: 3047b3e19d92SNick Piggin return err; 3048b3e19d92SNick Piggin 3049b3e19d92SNick Piggin out_mount: 3050b3e19d92SNick Piggin unregister_filesystem(&sock_fs_type); 3051b3e19d92SNick Piggin out_fs: 3052b3e19d92SNick Piggin goto out; 30531da177e4SLinus Torvalds } 30541da177e4SLinus Torvalds 305577d76ea3SAndi Kleen core_initcall(sock_init); /* early initcall */ 305677d76ea3SAndi Kleen 30571da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 30581da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq) 30591da177e4SLinus Torvalds { 3060648845abSTonghao Zhang seq_printf(seq, "sockets: used %d\n", 3061648845abSTonghao Zhang sock_inuse_get(seq->private)); 30621da177e4SLinus Torvalds } 30631da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */ 30641da177e4SLinus Torvalds 306589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT 306636fd633eSAl Viro static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) 30677a229387SArnd Bergmann { 30686b96018bSArnd Bergmann struct compat_ifconf ifc32; 30697a229387SArnd Bergmann struct ifconf ifc; 30707a229387SArnd Bergmann int err; 30717a229387SArnd Bergmann 30726b96018bSArnd Bergmann if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) 30737a229387SArnd Bergmann return -EFAULT; 30747a229387SArnd Bergmann 307536fd633eSAl Viro ifc.ifc_len = ifc32.ifc_len; 307636fd633eSAl Viro ifc.ifc_req = compat_ptr(ifc32.ifcbuf); 30777a229387SArnd Bergmann 307836fd633eSAl Viro rtnl_lock(); 307936fd633eSAl Viro err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq)); 308036fd633eSAl Viro rtnl_unlock(); 30817a229387SArnd Bergmann if (err) 30827a229387SArnd Bergmann return err; 30837a229387SArnd Bergmann 308436fd633eSAl Viro ifc32.ifc_len = ifc.ifc_len; 30856b96018bSArnd Bergmann if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) 30867a229387SArnd Bergmann return -EFAULT; 30877a229387SArnd Bergmann 30887a229387SArnd Bergmann return 0; 30897a229387SArnd Bergmann } 30907a229387SArnd Bergmann 30916b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) 30927a229387SArnd Bergmann { 30933a7da39dSBen Hutchings struct compat_ethtool_rxnfc __user *compat_rxnfc; 30943a7da39dSBen Hutchings bool convert_in = false, convert_out = false; 309544c02a2cSAl Viro size_t buf_size = 0; 309644c02a2cSAl Viro struct ethtool_rxnfc __user *rxnfc = NULL; 309744c02a2cSAl Viro struct ifreq ifr; 30983a7da39dSBen Hutchings u32 rule_cnt = 0, actual_rule_cnt; 30993a7da39dSBen Hutchings u32 ethcmd; 31007a229387SArnd Bergmann u32 data; 31013a7da39dSBen Hutchings int ret; 31027a229387SArnd Bergmann 31037a229387SArnd Bergmann if (get_user(data, &ifr32->ifr_ifru.ifru_data)) 31047a229387SArnd Bergmann return -EFAULT; 31057a229387SArnd Bergmann 31063a7da39dSBen Hutchings compat_rxnfc = compat_ptr(data); 31073a7da39dSBen Hutchings 31083a7da39dSBen Hutchings if (get_user(ethcmd, &compat_rxnfc->cmd)) 31097a229387SArnd Bergmann return -EFAULT; 31107a229387SArnd Bergmann 31113a7da39dSBen Hutchings /* Most ethtool structures are defined without padding. 31123a7da39dSBen Hutchings * Unfortunately struct ethtool_rxnfc is an exception. 31133a7da39dSBen Hutchings */ 31143a7da39dSBen Hutchings switch (ethcmd) { 31153a7da39dSBen Hutchings default: 31163a7da39dSBen Hutchings break; 31173a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLALL: 31183a7da39dSBen Hutchings /* Buffer size is variable */ 31193a7da39dSBen Hutchings if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) 31203a7da39dSBen Hutchings return -EFAULT; 31213a7da39dSBen Hutchings if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) 31223a7da39dSBen Hutchings return -ENOMEM; 31233a7da39dSBen Hutchings buf_size += rule_cnt * sizeof(u32); 31243a7da39dSBen Hutchings /* fall through */ 31253a7da39dSBen Hutchings case ETHTOOL_GRXRINGS: 31263a7da39dSBen Hutchings case ETHTOOL_GRXCLSRLCNT: 31273a7da39dSBen Hutchings case ETHTOOL_GRXCLSRULE: 312855664f32SBen Hutchings case ETHTOOL_SRXCLSRLINS: 31293a7da39dSBen Hutchings convert_out = true; 31303a7da39dSBen Hutchings /* fall through */ 31313a7da39dSBen Hutchings case ETHTOOL_SRXCLSRLDEL: 31323a7da39dSBen Hutchings buf_size += sizeof(struct ethtool_rxnfc); 31333a7da39dSBen Hutchings convert_in = true; 313444c02a2cSAl Viro rxnfc = compat_alloc_user_space(buf_size); 31353a7da39dSBen Hutchings break; 31363a7da39dSBen Hutchings } 31373a7da39dSBen Hutchings 313844c02a2cSAl Viro if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ)) 31393a7da39dSBen Hutchings return -EFAULT; 31403a7da39dSBen Hutchings 314144c02a2cSAl Viro ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc; 31423a7da39dSBen Hutchings 31433a7da39dSBen Hutchings if (convert_in) { 3144127fe533SAlexander Duyck /* We expect there to be holes between fs.m_ext and 31453a7da39dSBen Hutchings * fs.ring_cookie and at the end of fs, but nowhere else. 31463a7da39dSBen Hutchings */ 3147127fe533SAlexander Duyck BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + 3148127fe533SAlexander Duyck sizeof(compat_rxnfc->fs.m_ext) != 3149127fe533SAlexander Duyck offsetof(struct ethtool_rxnfc, fs.m_ext) + 3150127fe533SAlexander Duyck sizeof(rxnfc->fs.m_ext)); 31513a7da39dSBen Hutchings BUILD_BUG_ON( 31523a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.location) - 31533a7da39dSBen Hutchings offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != 31543a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.location) - 31553a7da39dSBen Hutchings offsetof(struct ethtool_rxnfc, fs.ring_cookie)); 31563a7da39dSBen Hutchings 31573a7da39dSBen Hutchings if (copy_in_user(rxnfc, compat_rxnfc, 3158954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.m_ext + 1) - 3159954b1244SStephen Hemminger (void __user *)rxnfc) || 31603a7da39dSBen Hutchings copy_in_user(&rxnfc->fs.ring_cookie, 31613a7da39dSBen Hutchings &compat_rxnfc->fs.ring_cookie, 3162954b1244SStephen Hemminger (void __user *)(&rxnfc->fs.location + 1) - 3163b6168562SWenwen Wang (void __user *)&rxnfc->fs.ring_cookie)) 3164b6168562SWenwen Wang return -EFAULT; 3165b6168562SWenwen Wang if (ethcmd == ETHTOOL_GRXCLSRLALL) { 3166b6168562SWenwen Wang if (put_user(rule_cnt, &rxnfc->rule_cnt)) 3167b6168562SWenwen Wang return -EFAULT; 3168b6168562SWenwen Wang } else if (copy_in_user(&rxnfc->rule_cnt, 3169b6168562SWenwen Wang &compat_rxnfc->rule_cnt, 31703a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 31713a7da39dSBen Hutchings return -EFAULT; 31723a7da39dSBen Hutchings } 31733a7da39dSBen Hutchings 317444c02a2cSAl Viro ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL); 31753a7da39dSBen Hutchings if (ret) 31763a7da39dSBen Hutchings return ret; 31773a7da39dSBen Hutchings 31783a7da39dSBen Hutchings if (convert_out) { 31793a7da39dSBen Hutchings if (copy_in_user(compat_rxnfc, rxnfc, 3180954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.m_ext + 1) - 3181954b1244SStephen Hemminger (const void __user *)rxnfc) || 31823a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->fs.ring_cookie, 31833a7da39dSBen Hutchings &rxnfc->fs.ring_cookie, 3184954b1244SStephen Hemminger (const void __user *)(&rxnfc->fs.location + 1) - 3185954b1244SStephen Hemminger (const void __user *)&rxnfc->fs.ring_cookie) || 31863a7da39dSBen Hutchings copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, 31873a7da39dSBen Hutchings sizeof(rxnfc->rule_cnt))) 31883a7da39dSBen Hutchings return -EFAULT; 31893a7da39dSBen Hutchings 31903a7da39dSBen Hutchings if (ethcmd == ETHTOOL_GRXCLSRLALL) { 31913a7da39dSBen Hutchings /* As an optimisation, we only copy the actual 31923a7da39dSBen Hutchings * number of rules that the underlying 31933a7da39dSBen Hutchings * function returned. Since Mallory might 31943a7da39dSBen Hutchings * change the rule count in user memory, we 31953a7da39dSBen Hutchings * check that it is less than the rule count 31963a7da39dSBen Hutchings * originally given (as the user buffer size), 31973a7da39dSBen Hutchings * which has been range-checked. 31983a7da39dSBen Hutchings */ 31993a7da39dSBen Hutchings if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) 32003a7da39dSBen Hutchings return -EFAULT; 32013a7da39dSBen Hutchings if (actual_rule_cnt < rule_cnt) 32023a7da39dSBen Hutchings rule_cnt = actual_rule_cnt; 32033a7da39dSBen Hutchings if (copy_in_user(&compat_rxnfc->rule_locs[0], 32043a7da39dSBen Hutchings &rxnfc->rule_locs[0], 32053a7da39dSBen Hutchings rule_cnt * sizeof(u32))) 32063a7da39dSBen Hutchings return -EFAULT; 32073a7da39dSBen Hutchings } 32083a7da39dSBen Hutchings } 32093a7da39dSBen Hutchings 32103a7da39dSBen Hutchings return 0; 32117a229387SArnd Bergmann } 32127a229387SArnd Bergmann 32137a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) 32147a50a240SArnd Bergmann { 32157a50a240SArnd Bergmann compat_uptr_t uptr32; 321644c02a2cSAl Viro struct ifreq ifr; 321744c02a2cSAl Viro void __user *saved; 321844c02a2cSAl Viro int err; 32197a50a240SArnd Bergmann 322044c02a2cSAl Viro if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq))) 32217a50a240SArnd Bergmann return -EFAULT; 32227a50a240SArnd Bergmann 32237a50a240SArnd Bergmann if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) 32247a50a240SArnd Bergmann return -EFAULT; 32257a50a240SArnd Bergmann 322644c02a2cSAl Viro saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc; 322744c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32); 32287a50a240SArnd Bergmann 322944c02a2cSAl Viro err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL); 323044c02a2cSAl Viro if (!err) { 323144c02a2cSAl Viro ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved; 323244c02a2cSAl Viro if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq))) 323344c02a2cSAl Viro err = -EFAULT; 32347a50a240SArnd Bergmann } 32357a229387SArnd Bergmann return err; 32367a229387SArnd Bergmann } 32377a229387SArnd Bergmann 3238590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */ 3239590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd, 32406b96018bSArnd Bergmann struct compat_ifreq __user *u_ifreq32) 32417a229387SArnd Bergmann { 324244c02a2cSAl Viro struct ifreq ifreq; 32437a229387SArnd Bergmann u32 data32; 32447a229387SArnd Bergmann 324544c02a2cSAl Viro if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ)) 32467a229387SArnd Bergmann return -EFAULT; 324744c02a2cSAl Viro if (get_user(data32, &u_ifreq32->ifr_data)) 32487a229387SArnd Bergmann return -EFAULT; 324944c02a2cSAl Viro ifreq.ifr_data = compat_ptr(data32); 32507a229387SArnd Bergmann 325144c02a2cSAl Viro return dev_ioctl(net, cmd, &ifreq, NULL); 3252a2116ed2SArnd Bergmann } 3253a2116ed2SArnd Bergmann 325437ac39bdSJohannes Berg static int compat_ifreq_ioctl(struct net *net, struct socket *sock, 325537ac39bdSJohannes Berg unsigned int cmd, 325637ac39bdSJohannes Berg struct compat_ifreq __user *uifr32) 325737ac39bdSJohannes Berg { 325837ac39bdSJohannes Berg struct ifreq __user *uifr; 325937ac39bdSJohannes Berg int err; 326037ac39bdSJohannes Berg 326137ac39bdSJohannes Berg /* Handle the fact that while struct ifreq has the same *layout* on 326237ac39bdSJohannes Berg * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data, 326337ac39bdSJohannes Berg * which are handled elsewhere, it still has different *size* due to 326437ac39bdSJohannes Berg * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit, 326537ac39bdSJohannes Berg * resulting in struct ifreq being 32 and 40 bytes respectively). 326637ac39bdSJohannes Berg * As a result, if the struct happens to be at the end of a page and 326737ac39bdSJohannes Berg * the next page isn't readable/writable, we get a fault. To prevent 326837ac39bdSJohannes Berg * that, copy back and forth to the full size. 326937ac39bdSJohannes Berg */ 327037ac39bdSJohannes Berg 327137ac39bdSJohannes Berg uifr = compat_alloc_user_space(sizeof(*uifr)); 327237ac39bdSJohannes Berg if (copy_in_user(uifr, uifr32, sizeof(*uifr32))) 327337ac39bdSJohannes Berg return -EFAULT; 327437ac39bdSJohannes Berg 327537ac39bdSJohannes Berg err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr); 327637ac39bdSJohannes Berg 327737ac39bdSJohannes Berg if (!err) { 327837ac39bdSJohannes Berg switch (cmd) { 327937ac39bdSJohannes Berg case SIOCGIFFLAGS: 328037ac39bdSJohannes Berg case SIOCGIFMETRIC: 328137ac39bdSJohannes Berg case SIOCGIFMTU: 328237ac39bdSJohannes Berg case SIOCGIFMEM: 328337ac39bdSJohannes Berg case SIOCGIFHWADDR: 328437ac39bdSJohannes Berg case SIOCGIFINDEX: 328537ac39bdSJohannes Berg case SIOCGIFADDR: 328637ac39bdSJohannes Berg case SIOCGIFBRDADDR: 328737ac39bdSJohannes Berg case SIOCGIFDSTADDR: 328837ac39bdSJohannes Berg case SIOCGIFNETMASK: 328937ac39bdSJohannes Berg case SIOCGIFPFLAGS: 329037ac39bdSJohannes Berg case SIOCGIFTXQLEN: 329137ac39bdSJohannes Berg case SIOCGMIIPHY: 329237ac39bdSJohannes Berg case SIOCGMIIREG: 3293c6c9fee3SJohannes Berg case SIOCGIFNAME: 329437ac39bdSJohannes Berg if (copy_in_user(uifr32, uifr, sizeof(*uifr32))) 329537ac39bdSJohannes Berg err = -EFAULT; 329637ac39bdSJohannes Berg break; 329737ac39bdSJohannes Berg } 329837ac39bdSJohannes Berg } 329937ac39bdSJohannes Berg return err; 330037ac39bdSJohannes Berg } 330137ac39bdSJohannes Berg 3302a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd, 3303a2116ed2SArnd Bergmann struct compat_ifreq __user *uifr32) 3304a2116ed2SArnd Bergmann { 3305a2116ed2SArnd Bergmann struct ifreq ifr; 3306a2116ed2SArnd Bergmann struct compat_ifmap __user *uifmap32; 3307a2116ed2SArnd Bergmann int err; 3308a2116ed2SArnd Bergmann 3309a2116ed2SArnd Bergmann uifmap32 = &uifr32->ifr_ifru.ifru_map; 3310a2116ed2SArnd Bergmann err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); 33113ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 33123ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 33133ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 33143ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.irq, &uifmap32->irq); 33153ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.dma, &uifmap32->dma); 33163ddc5b46SMathieu Desnoyers err |= get_user(ifr.ifr_map.port, &uifmap32->port); 3317a2116ed2SArnd Bergmann if (err) 3318a2116ed2SArnd Bergmann return -EFAULT; 3319a2116ed2SArnd Bergmann 332044c02a2cSAl Viro err = dev_ioctl(net, cmd, &ifr, NULL); 3321a2116ed2SArnd Bergmann 3322a2116ed2SArnd Bergmann if (cmd == SIOCGIFMAP && !err) { 33237a229387SArnd Bergmann err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); 33243ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); 33253ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); 33263ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); 33273ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.irq, &uifmap32->irq); 33283ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.dma, &uifmap32->dma); 33293ddc5b46SMathieu Desnoyers err |= put_user(ifr.ifr_map.port, &uifmap32->port); 33307a229387SArnd Bergmann if (err) 33317a229387SArnd Bergmann err = -EFAULT; 33327a229387SArnd Bergmann } 33337a229387SArnd Bergmann return err; 33347a229387SArnd Bergmann } 33357a229387SArnd Bergmann 33367a229387SArnd Bergmann struct rtentry32 { 33377a229387SArnd Bergmann u32 rt_pad1; 33387a229387SArnd Bergmann struct sockaddr rt_dst; /* target address */ 33397a229387SArnd Bergmann struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ 33407a229387SArnd Bergmann struct sockaddr rt_genmask; /* target network mask (IP) */ 33417a229387SArnd Bergmann unsigned short rt_flags; 33427a229387SArnd Bergmann short rt_pad2; 33437a229387SArnd Bergmann u32 rt_pad3; 33447a229387SArnd Bergmann unsigned char rt_tos; 33457a229387SArnd Bergmann unsigned char rt_class; 33467a229387SArnd Bergmann short rt_pad4; 33477a229387SArnd Bergmann short rt_metric; /* +1 for binary compatibility! */ 33487a229387SArnd Bergmann /* char * */ u32 rt_dev; /* forcing the device at add */ 33497a229387SArnd Bergmann u32 rt_mtu; /* per route MTU/Window */ 33507a229387SArnd Bergmann u32 rt_window; /* Window clamping */ 33517a229387SArnd Bergmann unsigned short rt_irtt; /* Initial RTT */ 33527a229387SArnd Bergmann }; 33537a229387SArnd Bergmann 33547a229387SArnd Bergmann struct in6_rtmsg32 { 33557a229387SArnd Bergmann struct in6_addr rtmsg_dst; 33567a229387SArnd Bergmann struct in6_addr rtmsg_src; 33577a229387SArnd Bergmann struct in6_addr rtmsg_gateway; 33587a229387SArnd Bergmann u32 rtmsg_type; 33597a229387SArnd Bergmann u16 rtmsg_dst_len; 33607a229387SArnd Bergmann u16 rtmsg_src_len; 33617a229387SArnd Bergmann u32 rtmsg_metric; 33627a229387SArnd Bergmann u32 rtmsg_info; 33637a229387SArnd Bergmann u32 rtmsg_flags; 33647a229387SArnd Bergmann s32 rtmsg_ifindex; 33657a229387SArnd Bergmann }; 33667a229387SArnd Bergmann 33676b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock, 33686b96018bSArnd Bergmann unsigned int cmd, void __user *argp) 33697a229387SArnd Bergmann { 33707a229387SArnd Bergmann int ret; 33717a229387SArnd Bergmann void *r = NULL; 33727a229387SArnd Bergmann struct in6_rtmsg r6; 33737a229387SArnd Bergmann struct rtentry r4; 33747a229387SArnd Bergmann char devname[16]; 33757a229387SArnd Bergmann u32 rtdev; 33767a229387SArnd Bergmann mm_segment_t old_fs = get_fs(); 33777a229387SArnd Bergmann 33786b96018bSArnd Bergmann if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */ 33796b96018bSArnd Bergmann struct in6_rtmsg32 __user *ur6 = argp; 33807a229387SArnd Bergmann ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst), 33817a229387SArnd Bergmann 3 * sizeof(struct in6_addr)); 33823ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type)); 33833ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); 33843ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); 33853ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric)); 33863ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info)); 33873ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags)); 33883ddc5b46SMathieu Desnoyers ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); 33897a229387SArnd Bergmann 33907a229387SArnd Bergmann r = (void *) &r6; 33917a229387SArnd Bergmann } else { /* ipv4 */ 33926b96018bSArnd Bergmann struct rtentry32 __user *ur4 = argp; 33937a229387SArnd Bergmann ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst), 33947a229387SArnd Bergmann 3 * sizeof(struct sockaddr)); 33953ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_flags, &(ur4->rt_flags)); 33963ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_metric, &(ur4->rt_metric)); 33973ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu)); 33983ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_window, &(ur4->rt_window)); 33993ddc5b46SMathieu Desnoyers ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt)); 34003ddc5b46SMathieu Desnoyers ret |= get_user(rtdev, &(ur4->rt_dev)); 34017a229387SArnd Bergmann if (rtdev) { 34027a229387SArnd Bergmann ret |= copy_from_user(devname, compat_ptr(rtdev), 15); 3403c3f52ae6Sstephen hemminger r4.rt_dev = (char __user __force *)devname; 3404c3f52ae6Sstephen hemminger devname[15] = 0; 34057a229387SArnd Bergmann } else 34067a229387SArnd Bergmann r4.rt_dev = NULL; 34077a229387SArnd Bergmann 34087a229387SArnd Bergmann r = (void *) &r4; 34097a229387SArnd Bergmann } 34107a229387SArnd Bergmann 34117a229387SArnd Bergmann if (ret) { 34127a229387SArnd Bergmann ret = -EFAULT; 34137a229387SArnd Bergmann goto out; 34147a229387SArnd Bergmann } 34157a229387SArnd Bergmann 34167a229387SArnd Bergmann set_fs(KERNEL_DS); 341763ff03abSJohannes Berg ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); 34187a229387SArnd Bergmann set_fs(old_fs); 34197a229387SArnd Bergmann 34207a229387SArnd Bergmann out: 34217a229387SArnd Bergmann return ret; 34227a229387SArnd Bergmann } 34237a229387SArnd Bergmann 34247a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE 34257a229387SArnd Bergmann * for some operations; this forces use of the newer bridge-utils that 342625985edcSLucas De Marchi * use compatible ioctls 34277a229387SArnd Bergmann */ 34286b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp) 34297a229387SArnd Bergmann { 34306b96018bSArnd Bergmann compat_ulong_t tmp; 34317a229387SArnd Bergmann 34326b96018bSArnd Bergmann if (get_user(tmp, argp)) 34337a229387SArnd Bergmann return -EFAULT; 34347a229387SArnd Bergmann if (tmp == BRCTL_GET_VERSION) 34357a229387SArnd Bergmann return BRCTL_VERSION + 1; 34367a229387SArnd Bergmann return -EINVAL; 34377a229387SArnd Bergmann } 34387a229387SArnd Bergmann 34396b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, 34406b96018bSArnd Bergmann unsigned int cmd, unsigned long arg) 34416b96018bSArnd Bergmann { 34426b96018bSArnd Bergmann void __user *argp = compat_ptr(arg); 34436b96018bSArnd Bergmann struct sock *sk = sock->sk; 34446b96018bSArnd Bergmann struct net *net = sock_net(sk); 34457a229387SArnd Bergmann 34466b96018bSArnd Bergmann if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 3447590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 34487a229387SArnd Bergmann 34496b96018bSArnd Bergmann switch (cmd) { 34506b96018bSArnd Bergmann case SIOCSIFBR: 34516b96018bSArnd Bergmann case SIOCGIFBR: 34526b96018bSArnd Bergmann return old_bridge_ioctl(argp); 34536b96018bSArnd Bergmann case SIOCGIFCONF: 345436fd633eSAl Viro return compat_dev_ifconf(net, argp); 34556b96018bSArnd Bergmann case SIOCETHTOOL: 34566b96018bSArnd Bergmann return ethtool_ioctl(net, argp); 34577a50a240SArnd Bergmann case SIOCWANDEV: 34587a50a240SArnd Bergmann return compat_siocwandev(net, argp); 3459a2116ed2SArnd Bergmann case SIOCGIFMAP: 3460a2116ed2SArnd Bergmann case SIOCSIFMAP: 3461a2116ed2SArnd Bergmann return compat_sioc_ifmap(net, cmd, argp); 34626b96018bSArnd Bergmann case SIOCADDRT: 34636b96018bSArnd Bergmann case SIOCDELRT: 34646b96018bSArnd Bergmann return routing_ioctl(net, sock, cmd, argp); 34650768e170SArnd Bergmann case SIOCGSTAMP_OLD: 34660768e170SArnd Bergmann case SIOCGSTAMPNS_OLD: 3467c7cbdbf2SArnd Bergmann if (!sock->ops->gettstamp) 3468c7cbdbf2SArnd Bergmann return -ENOIOCTLCMD; 34690768e170SArnd Bergmann return sock->ops->gettstamp(sock, argp, cmd == SIOCGSTAMP_OLD, 3470c7cbdbf2SArnd Bergmann !COMPAT_USE_64BIT_TIME); 3471c7cbdbf2SArnd Bergmann 3472590d4693SBen Hutchings case SIOCBONDSLAVEINFOQUERY: 3473590d4693SBen Hutchings case SIOCBONDINFOQUERY: 3474a2116ed2SArnd Bergmann case SIOCSHWTSTAMP: 3475fd468c74SBen Hutchings case SIOCGHWTSTAMP: 3476590d4693SBen Hutchings return compat_ifr_data_ioctl(net, cmd, argp); 34777a229387SArnd Bergmann 34786b96018bSArnd Bergmann case FIOSETOWN: 34796b96018bSArnd Bergmann case SIOCSPGRP: 34806b96018bSArnd Bergmann case FIOGETOWN: 34816b96018bSArnd Bergmann case SIOCGPGRP: 34826b96018bSArnd Bergmann case SIOCBRADDBR: 34836b96018bSArnd Bergmann case SIOCBRDELBR: 34846b96018bSArnd Bergmann case SIOCGIFVLAN: 34856b96018bSArnd Bergmann case SIOCSIFVLAN: 34866b96018bSArnd Bergmann case SIOCADDDLCI: 34876b96018bSArnd Bergmann case SIOCDELDLCI: 3488c62cce2cSAndrey Vagin case SIOCGSKNS: 34890768e170SArnd Bergmann case SIOCGSTAMP_NEW: 34900768e170SArnd Bergmann case SIOCGSTAMPNS_NEW: 34916b96018bSArnd Bergmann return sock_ioctl(file, cmd, arg); 34926b96018bSArnd Bergmann 34936b96018bSArnd Bergmann case SIOCGIFFLAGS: 34946b96018bSArnd Bergmann case SIOCSIFFLAGS: 34956b96018bSArnd Bergmann case SIOCGIFMETRIC: 34966b96018bSArnd Bergmann case SIOCSIFMETRIC: 34976b96018bSArnd Bergmann case SIOCGIFMTU: 34986b96018bSArnd Bergmann case SIOCSIFMTU: 34996b96018bSArnd Bergmann case SIOCGIFMEM: 35006b96018bSArnd Bergmann case SIOCSIFMEM: 35016b96018bSArnd Bergmann case SIOCGIFHWADDR: 35026b96018bSArnd Bergmann case SIOCSIFHWADDR: 35036b96018bSArnd Bergmann case SIOCADDMULTI: 35046b96018bSArnd Bergmann case SIOCDELMULTI: 35056b96018bSArnd Bergmann case SIOCGIFINDEX: 35066b96018bSArnd Bergmann case SIOCGIFADDR: 35076b96018bSArnd Bergmann case SIOCSIFADDR: 35086b96018bSArnd Bergmann case SIOCSIFHWBROADCAST: 35096b96018bSArnd Bergmann case SIOCDIFADDR: 35106b96018bSArnd Bergmann case SIOCGIFBRDADDR: 35116b96018bSArnd Bergmann case SIOCSIFBRDADDR: 35126b96018bSArnd Bergmann case SIOCGIFDSTADDR: 35136b96018bSArnd Bergmann case SIOCSIFDSTADDR: 35146b96018bSArnd Bergmann case SIOCGIFNETMASK: 35156b96018bSArnd Bergmann case SIOCSIFNETMASK: 35166b96018bSArnd Bergmann case SIOCSIFPFLAGS: 35176b96018bSArnd Bergmann case SIOCGIFPFLAGS: 35186b96018bSArnd Bergmann case SIOCGIFTXQLEN: 35196b96018bSArnd Bergmann case SIOCSIFTXQLEN: 35206b96018bSArnd Bergmann case SIOCBRADDIF: 35216b96018bSArnd Bergmann case SIOCBRDELIF: 3522c6c9fee3SJohannes Berg case SIOCGIFNAME: 35239177efd3SArnd Bergmann case SIOCSIFNAME: 35249177efd3SArnd Bergmann case SIOCGMIIPHY: 35259177efd3SArnd Bergmann case SIOCGMIIREG: 35269177efd3SArnd Bergmann case SIOCSMIIREG: 3527f92d4fc9SAl Viro case SIOCBONDENSLAVE: 3528f92d4fc9SAl Viro case SIOCBONDRELEASE: 3529f92d4fc9SAl Viro case SIOCBONDSETHWADDR: 3530f92d4fc9SAl Viro case SIOCBONDCHANGEACTIVE: 353137ac39bdSJohannes Berg return compat_ifreq_ioctl(net, sock, cmd, argp); 353237ac39bdSJohannes Berg 35336b96018bSArnd Bergmann case SIOCSARP: 35346b96018bSArnd Bergmann case SIOCGARP: 35356b96018bSArnd Bergmann case SIOCDARP: 35366b96018bSArnd Bergmann case SIOCATMARK: 353763ff03abSJohannes Berg return sock_do_ioctl(net, sock, cmd, arg); 35389177efd3SArnd Bergmann } 35399177efd3SArnd Bergmann 35406b96018bSArnd Bergmann return -ENOIOCTLCMD; 35416b96018bSArnd Bergmann } 35427a229387SArnd Bergmann 354395c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd, 354489bbfc95SShaun Pereira unsigned long arg) 354589bbfc95SShaun Pereira { 354689bbfc95SShaun Pereira struct socket *sock = file->private_data; 354789bbfc95SShaun Pereira int ret = -ENOIOCTLCMD; 354887de87d5SDavid S. Miller struct sock *sk; 354987de87d5SDavid S. Miller struct net *net; 355087de87d5SDavid S. Miller 355187de87d5SDavid S. Miller sk = sock->sk; 355287de87d5SDavid S. Miller net = sock_net(sk); 355389bbfc95SShaun Pereira 355489bbfc95SShaun Pereira if (sock->ops->compat_ioctl) 355589bbfc95SShaun Pereira ret = sock->ops->compat_ioctl(sock, cmd, arg); 355689bbfc95SShaun Pereira 355787de87d5SDavid S. Miller if (ret == -ENOIOCTLCMD && 355887de87d5SDavid S. Miller (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) 355987de87d5SDavid S. Miller ret = compat_wext_handle_ioctl(net, cmd, arg); 356087de87d5SDavid S. Miller 35616b96018bSArnd Bergmann if (ret == -ENOIOCTLCMD) 35626b96018bSArnd Bergmann ret = compat_sock_ioctl_trans(file, sock, cmd, arg); 35636b96018bSArnd Bergmann 356489bbfc95SShaun Pereira return ret; 356589bbfc95SShaun Pereira } 356689bbfc95SShaun Pereira #endif 356789bbfc95SShaun Pereira 35688a3c245cSPedro Tammela /** 35698a3c245cSPedro Tammela * kernel_bind - bind an address to a socket (kernel space) 35708a3c245cSPedro Tammela * @sock: socket 35718a3c245cSPedro Tammela * @addr: address 35728a3c245cSPedro Tammela * @addrlen: length of address 35738a3c245cSPedro Tammela * 35748a3c245cSPedro Tammela * Returns 0 or an error. 35758a3c245cSPedro Tammela */ 35768a3c245cSPedro Tammela 3577ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) 3578ac5a488eSSridhar Samudrala { 3579ac5a488eSSridhar Samudrala return sock->ops->bind(sock, addr, addrlen); 3580ac5a488eSSridhar Samudrala } 3581c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind); 3582ac5a488eSSridhar Samudrala 35838a3c245cSPedro Tammela /** 35848a3c245cSPedro Tammela * kernel_listen - move socket to listening state (kernel space) 35858a3c245cSPedro Tammela * @sock: socket 35868a3c245cSPedro Tammela * @backlog: pending connections queue size 35878a3c245cSPedro Tammela * 35888a3c245cSPedro Tammela * Returns 0 or an error. 35898a3c245cSPedro Tammela */ 35908a3c245cSPedro Tammela 3591ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog) 3592ac5a488eSSridhar Samudrala { 3593ac5a488eSSridhar Samudrala return sock->ops->listen(sock, backlog); 3594ac5a488eSSridhar Samudrala } 3595c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen); 3596ac5a488eSSridhar Samudrala 35978a3c245cSPedro Tammela /** 35988a3c245cSPedro Tammela * kernel_accept - accept a connection (kernel space) 35998a3c245cSPedro Tammela * @sock: listening socket 36008a3c245cSPedro Tammela * @newsock: new connected socket 36018a3c245cSPedro Tammela * @flags: flags 36028a3c245cSPedro Tammela * 36038a3c245cSPedro Tammela * @flags must be SOCK_CLOEXEC, SOCK_NONBLOCK or 0. 36048a3c245cSPedro Tammela * If it fails, @newsock is guaranteed to be %NULL. 36058a3c245cSPedro Tammela * Returns 0 or an error. 36068a3c245cSPedro Tammela */ 36078a3c245cSPedro Tammela 3608ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags) 3609ac5a488eSSridhar Samudrala { 3610ac5a488eSSridhar Samudrala struct sock *sk = sock->sk; 3611ac5a488eSSridhar Samudrala int err; 3612ac5a488eSSridhar Samudrala 3613ac5a488eSSridhar Samudrala err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, 3614ac5a488eSSridhar Samudrala newsock); 3615ac5a488eSSridhar Samudrala if (err < 0) 3616ac5a488eSSridhar Samudrala goto done; 3617ac5a488eSSridhar Samudrala 3618cdfbabfbSDavid Howells err = sock->ops->accept(sock, *newsock, flags, true); 3619ac5a488eSSridhar Samudrala if (err < 0) { 3620ac5a488eSSridhar Samudrala sock_release(*newsock); 3621fa8705b0STony Battersby *newsock = NULL; 3622ac5a488eSSridhar Samudrala goto done; 3623ac5a488eSSridhar Samudrala } 3624ac5a488eSSridhar Samudrala 3625ac5a488eSSridhar Samudrala (*newsock)->ops = sock->ops; 36261b08534eSWei Yongjun __module_get((*newsock)->ops->owner); 3627ac5a488eSSridhar Samudrala 3628ac5a488eSSridhar Samudrala done: 3629ac5a488eSSridhar Samudrala return err; 3630ac5a488eSSridhar Samudrala } 3631c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept); 3632ac5a488eSSridhar Samudrala 36338a3c245cSPedro Tammela /** 36348a3c245cSPedro Tammela * kernel_connect - connect a socket (kernel space) 36358a3c245cSPedro Tammela * @sock: socket 36368a3c245cSPedro Tammela * @addr: address 36378a3c245cSPedro Tammela * @addrlen: address length 36388a3c245cSPedro Tammela * @flags: flags (O_NONBLOCK, ...) 36398a3c245cSPedro Tammela * 36408a3c245cSPedro Tammela * For datagram sockets, @addr is the addres to which datagrams are sent 36418a3c245cSPedro Tammela * by default, and the only address from which datagrams are received. 36428a3c245cSPedro Tammela * For stream sockets, attempts to connect to @addr. 36438a3c245cSPedro Tammela * Returns 0 or an error code. 36448a3c245cSPedro Tammela */ 36458a3c245cSPedro Tammela 3646ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, 3647ac5a488eSSridhar Samudrala int flags) 3648ac5a488eSSridhar Samudrala { 3649ac5a488eSSridhar Samudrala return sock->ops->connect(sock, addr, addrlen, flags); 3650ac5a488eSSridhar Samudrala } 3651c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect); 3652ac5a488eSSridhar Samudrala 36538a3c245cSPedro Tammela /** 36548a3c245cSPedro Tammela * kernel_getsockname - get the address which the socket is bound (kernel space) 36558a3c245cSPedro Tammela * @sock: socket 36568a3c245cSPedro Tammela * @addr: address holder 36578a3c245cSPedro Tammela * 36588a3c245cSPedro Tammela * Fills the @addr pointer with the address which the socket is bound. 36598a3c245cSPedro Tammela * Returns 0 or an error code. 36608a3c245cSPedro Tammela */ 36618a3c245cSPedro Tammela 36629b2c45d4SDenys Vlasenko int kernel_getsockname(struct socket *sock, struct sockaddr *addr) 3663ac5a488eSSridhar Samudrala { 36649b2c45d4SDenys Vlasenko return sock->ops->getname(sock, addr, 0); 3665ac5a488eSSridhar Samudrala } 3666c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname); 3667ac5a488eSSridhar Samudrala 36688a3c245cSPedro Tammela /** 36698a3c245cSPedro Tammela * kernel_peername - get the address which the socket is connected (kernel space) 36708a3c245cSPedro Tammela * @sock: socket 36718a3c245cSPedro Tammela * @addr: address holder 36728a3c245cSPedro Tammela * 36738a3c245cSPedro Tammela * Fills the @addr pointer with the address which the socket is connected. 36748a3c245cSPedro Tammela * Returns 0 or an error code. 36758a3c245cSPedro Tammela */ 36768a3c245cSPedro Tammela 36779b2c45d4SDenys Vlasenko int kernel_getpeername(struct socket *sock, struct sockaddr *addr) 3678ac5a488eSSridhar Samudrala { 36799b2c45d4SDenys Vlasenko return sock->ops->getname(sock, addr, 1); 3680ac5a488eSSridhar Samudrala } 3681c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername); 3682ac5a488eSSridhar Samudrala 36838a3c245cSPedro Tammela /** 36848a3c245cSPedro Tammela * kernel_getsockopt - get a socket option (kernel space) 36858a3c245cSPedro Tammela * @sock: socket 36868a3c245cSPedro Tammela * @level: API level (SOL_SOCKET, ...) 36878a3c245cSPedro Tammela * @optname: option tag 36888a3c245cSPedro Tammela * @optval: option value 36898a3c245cSPedro Tammela * @optlen: option length 36908a3c245cSPedro Tammela * 36918a3c245cSPedro Tammela * Assigns the option length to @optlen. 36928a3c245cSPedro Tammela * Returns 0 or an error. 36938a3c245cSPedro Tammela */ 36948a3c245cSPedro Tammela 3695ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname, 3696ac5a488eSSridhar Samudrala char *optval, int *optlen) 3697ac5a488eSSridhar Samudrala { 3698ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3699fb8621bbSNamhyung Kim char __user *uoptval; 3700fb8621bbSNamhyung Kim int __user *uoptlen; 3701ac5a488eSSridhar Samudrala int err; 3702ac5a488eSSridhar Samudrala 3703fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3704fb8621bbSNamhyung Kim uoptlen = (int __user __force *) optlen; 3705fb8621bbSNamhyung Kim 3706ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3707ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3708fb8621bbSNamhyung Kim err = sock_getsockopt(sock, level, optname, uoptval, uoptlen); 3709ac5a488eSSridhar Samudrala else 3710fb8621bbSNamhyung Kim err = sock->ops->getsockopt(sock, level, optname, uoptval, 3711fb8621bbSNamhyung Kim uoptlen); 3712ac5a488eSSridhar Samudrala set_fs(oldfs); 3713ac5a488eSSridhar Samudrala return err; 3714ac5a488eSSridhar Samudrala } 3715c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt); 3716ac5a488eSSridhar Samudrala 37178a3c245cSPedro Tammela /** 37188a3c245cSPedro Tammela * kernel_setsockopt - set a socket option (kernel space) 37198a3c245cSPedro Tammela * @sock: socket 37208a3c245cSPedro Tammela * @level: API level (SOL_SOCKET, ...) 37218a3c245cSPedro Tammela * @optname: option tag 37228a3c245cSPedro Tammela * @optval: option value 37238a3c245cSPedro Tammela * @optlen: option length 37248a3c245cSPedro Tammela * 37258a3c245cSPedro Tammela * Returns 0 or an error. 37268a3c245cSPedro Tammela */ 37278a3c245cSPedro Tammela 3728ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname, 3729b7058842SDavid S. Miller char *optval, unsigned int optlen) 3730ac5a488eSSridhar Samudrala { 3731ac5a488eSSridhar Samudrala mm_segment_t oldfs = get_fs(); 3732fb8621bbSNamhyung Kim char __user *uoptval; 3733ac5a488eSSridhar Samudrala int err; 3734ac5a488eSSridhar Samudrala 3735fb8621bbSNamhyung Kim uoptval = (char __user __force *) optval; 3736fb8621bbSNamhyung Kim 3737ac5a488eSSridhar Samudrala set_fs(KERNEL_DS); 3738ac5a488eSSridhar Samudrala if (level == SOL_SOCKET) 3739fb8621bbSNamhyung Kim err = sock_setsockopt(sock, level, optname, uoptval, optlen); 3740ac5a488eSSridhar Samudrala else 3741fb8621bbSNamhyung Kim err = sock->ops->setsockopt(sock, level, optname, uoptval, 3742ac5a488eSSridhar Samudrala optlen); 3743ac5a488eSSridhar Samudrala set_fs(oldfs); 3744ac5a488eSSridhar Samudrala return err; 3745ac5a488eSSridhar Samudrala } 3746c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt); 3747ac5a488eSSridhar Samudrala 37488a3c245cSPedro Tammela /** 37498a3c245cSPedro Tammela * kernel_sendpage - send a &page through a socket (kernel space) 37508a3c245cSPedro Tammela * @sock: socket 37518a3c245cSPedro Tammela * @page: page 37528a3c245cSPedro Tammela * @offset: page offset 37538a3c245cSPedro Tammela * @size: total size in bytes 37548a3c245cSPedro Tammela * @flags: flags (MSG_DONTWAIT, ...) 37558a3c245cSPedro Tammela * 37568a3c245cSPedro Tammela * Returns the total amount sent in bytes or an error. 37578a3c245cSPedro Tammela */ 37588a3c245cSPedro Tammela 3759ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset, 3760ac5a488eSSridhar Samudrala size_t size, int flags) 3761ac5a488eSSridhar Samudrala { 3762ac5a488eSSridhar Samudrala if (sock->ops->sendpage) 3763ac5a488eSSridhar Samudrala return sock->ops->sendpage(sock, page, offset, size, flags); 3764ac5a488eSSridhar Samudrala 3765ac5a488eSSridhar Samudrala return sock_no_sendpage(sock, page, offset, size, flags); 3766ac5a488eSSridhar Samudrala } 3767c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage); 3768ac5a488eSSridhar Samudrala 37698a3c245cSPedro Tammela /** 37708a3c245cSPedro Tammela * kernel_sendpage_locked - send a &page through the locked sock (kernel space) 37718a3c245cSPedro Tammela * @sk: sock 37728a3c245cSPedro Tammela * @page: page 37738a3c245cSPedro Tammela * @offset: page offset 37748a3c245cSPedro Tammela * @size: total size in bytes 37758a3c245cSPedro Tammela * @flags: flags (MSG_DONTWAIT, ...) 37768a3c245cSPedro Tammela * 37778a3c245cSPedro Tammela * Returns the total amount sent in bytes or an error. 37788a3c245cSPedro Tammela * Caller must hold @sk. 37798a3c245cSPedro Tammela */ 37808a3c245cSPedro Tammela 3781306b13ebSTom Herbert int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset, 3782306b13ebSTom Herbert size_t size, int flags) 3783306b13ebSTom Herbert { 3784306b13ebSTom Herbert struct socket *sock = sk->sk_socket; 3785306b13ebSTom Herbert 3786306b13ebSTom Herbert if (sock->ops->sendpage_locked) 3787306b13ebSTom Herbert return sock->ops->sendpage_locked(sk, page, offset, size, 3788306b13ebSTom Herbert flags); 3789306b13ebSTom Herbert 3790306b13ebSTom Herbert return sock_no_sendpage_locked(sk, page, offset, size, flags); 3791306b13ebSTom Herbert } 3792306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendpage_locked); 3793306b13ebSTom Herbert 37948a3c245cSPedro Tammela /** 37958a3c245cSPedro Tammela * kernel_shutdown - shut down part of a full-duplex connection (kernel space) 37968a3c245cSPedro Tammela * @sock: socket 37978a3c245cSPedro Tammela * @how: connection part 37988a3c245cSPedro Tammela * 37998a3c245cSPedro Tammela * Returns 0 or an error. 38008a3c245cSPedro Tammela */ 38018a3c245cSPedro Tammela 380291cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) 380391cf45f0STrond Myklebust { 380491cf45f0STrond Myklebust return sock->ops->shutdown(sock, how); 380591cf45f0STrond Myklebust } 380691cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown); 3807113c3075SR. Parameswaran 38088a3c245cSPedro Tammela /** 38098a3c245cSPedro Tammela * kernel_sock_ip_overhead - returns the IP overhead imposed by a socket 38108a3c245cSPedro Tammela * @sk: socket 38118a3c245cSPedro Tammela * 38128a3c245cSPedro Tammela * This routine returns the IP overhead imposed by a socket i.e. 3813113c3075SR. Parameswaran * the length of the underlying IP header, depending on whether 3814113c3075SR. Parameswaran * this is an IPv4 or IPv6 socket and the length from IP options turned 381557240d00SR. Parameswaran * on at the socket. Assumes that the caller has a lock on the socket. 3816113c3075SR. Parameswaran */ 38178a3c245cSPedro Tammela 3818113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk) 3819113c3075SR. Parameswaran { 3820113c3075SR. Parameswaran struct inet_sock *inet; 3821113c3075SR. Parameswaran struct ip_options_rcu *opt; 3822113c3075SR. Parameswaran u32 overhead = 0; 3823113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6) 3824113c3075SR. Parameswaran struct ipv6_pinfo *np; 3825113c3075SR. Parameswaran struct ipv6_txoptions *optv6 = NULL; 3826113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */ 3827113c3075SR. Parameswaran 3828113c3075SR. Parameswaran if (!sk) 3829113c3075SR. Parameswaran return overhead; 3830113c3075SR. Parameswaran 3831113c3075SR. Parameswaran switch (sk->sk_family) { 3832113c3075SR. Parameswaran case AF_INET: 3833113c3075SR. Parameswaran inet = inet_sk(sk); 3834113c3075SR. Parameswaran overhead += sizeof(struct iphdr); 3835113c3075SR. Parameswaran opt = rcu_dereference_protected(inet->inet_opt, 3836614d79c0Sstephen hemminger sock_owned_by_user(sk)); 3837113c3075SR. Parameswaran if (opt) 3838113c3075SR. Parameswaran overhead += opt->opt.optlen; 3839113c3075SR. Parameswaran return overhead; 3840113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6) 3841113c3075SR. Parameswaran case AF_INET6: 3842113c3075SR. Parameswaran np = inet6_sk(sk); 3843113c3075SR. Parameswaran overhead += sizeof(struct ipv6hdr); 3844113c3075SR. Parameswaran if (np) 3845113c3075SR. Parameswaran optv6 = rcu_dereference_protected(np->opt, 3846614d79c0Sstephen hemminger sock_owned_by_user(sk)); 3847113c3075SR. Parameswaran if (optv6) 3848113c3075SR. Parameswaran overhead += (optv6->opt_flen + optv6->opt_nflen); 3849113c3075SR. Parameswaran return overhead; 3850113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */ 3851113c3075SR. Parameswaran default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */ 3852113c3075SR. Parameswaran return overhead; 3853113c3075SR. Parameswaran } 3854113c3075SR. Parameswaran } 3855113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead); 3856