cregit-Linux how code gets into the kernel

Release 4.7 net/socket.c

Directory: net
/*
 * NET          An implementation of the SOCKET network access protocol.
 *
 * Version:     @(#)socket.c    1.1.93  18/02/95
 *
 * Authors:     Orest Zborowski, <obz@Kodak.COM>
 *              Ross Biro
 *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 *
 * Fixes:
 *              Anonymous       :       NOTSOCK/BADF cleanup. Error fix in
 *                                      shutdown()
 *              Alan Cox        :       verify_area() fixes
 *              Alan Cox        :       Removed DDI
 *              Jonathan Kamens :       SOCK_DGRAM reconnect bug
 *              Alan Cox        :       Moved a load of checks to the very
 *                                      top level.
 *              Alan Cox        :       Move address structures to/from user
 *                                      mode above the protocol layers.
 *              Rob Janssen     :       Allow 0 length sends.
 *              Alan Cox        :       Asynchronous I/O support (cribbed from the
 *                                      tty drivers).
 *              Niibe Yutaka    :       Asynchronous I/O for writes (4.4BSD style)
 *              Jeff Uphoff     :       Made max number of sockets command-line
 *                                      configurable.
 *              Matti Aarnio    :       Made the number of sockets dynamic,
 *                                      to be allocated when needed, and mr.
 *                                      Uphoff's max is used as max to be
 *                                      allowed to allocate.
 *              Linus           :       Argh. removed all the socket allocation
 *                                      altogether: it's in the inode now.
 *              Alan Cox        :       Made sock_alloc()/sock_release() public
 *                                      for NetROM and future kernel nfsd type
 *                                      stuff.
 *              Alan Cox        :       sendmsg/recvmsg basics.
 *              Tom Dyas        :       Export net symbols.
 *              Marcin Dalecki  :       Fixed problems with CONFIG_NET="n".
 *              Alan Cox        :       Added thread locking to sys_* calls
 *                                      for sockets. May have errors at the
 *                                      moment.
 *              Kevin Buhr      :       Fixed the dumb errors in the above.
 *              Andi Kleen      :       Some small cleanups, optimizations,
 *                                      and fixed a copy_from_user() bug.
 *              Tigran Aivazian :       sys_send(args) calls sys_sendto(args, NULL, 0)
 *              Tigran Aivazian :       Made listen(2) backlog sanity checks
 *                                      protocol-independent
 *
 *
 *              This program is free software; you can redistribute it and/or
 *              modify it under the terms of the GNU General Public License
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 *
 *
 *      This module is effectively the top level interface to the BSD socket
 *      paradigm.
 *
 *      Based upon Swansea University Computer Society NET3.039
 */

#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/file.h>
#include <linux/net.h>
#include <linux/interrupt.h>
#include <linux/thread_info.h>
#include <linux/rcupdate.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/mutex.h>
#include <linux/if_bridge.h>
#include <linux/if_frad.h>
#include <linux/if_vlan.h>
#include <linux/ptp_classify.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/cache.h>
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/compat.h>
#include <linux/kmod.h>
#include <linux/audit.h>
#include <linux/wireless.h>
#include <linux/nsproxy.h>
#include <linux/magic.h>
#include <linux/slab.h>
#include <linux/xattr.h>

#include <asm/uaccess.h>
#include <asm/unistd.h>

#include <net/compat.h>
#include <net/wext.h>
#include <net/cls_cgroup.h>

#include <net/sock.h>
#include <linux/netfilter.h>

#include <linux/if_tun.h>
#include <linux/ipv6_route.h>
#include <linux/route.h>
#include <linux/sockios.h>
#include <linux/atalk.h>
#include <net/busy_poll.h>
#include <linux/errqueue.h>

#ifdef CONFIG_NET_RX_BUSY_POLL

unsigned int sysctl_net_busy_read __read_mostly;

unsigned int sysctl_net_busy_poll __read_mostly;
#endif

static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
static int sock_mmap(struct file *file, struct vm_area_struct *vma);

static int sock_close(struct inode *inode, struct file *file);
static unsigned int sock_poll(struct file *file,
			      struct poll_table_struct *wait);
static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
#ifdef CONFIG_COMPAT
static long compat_sock_ioctl(struct file *file,
			      unsigned int cmd, unsigned long arg);
#endif
static int sock_fasync(int fd, struct file *filp, int on);
static ssize_t sock_sendpage(struct file *file, struct page *page,
			     int offset, size_t size, loff_t *ppos, int more);
static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
				struct pipe_inode_info *pipe, size_t len,
				unsigned int flags);

/*
 *      Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
 *      in the operation structures but are done directly via the socketcall() multiplexor.
 */


static const struct file_operations socket_file_ops = {
	.owner =	THIS_MODULE,
	.llseek =	no_llseek,
	.read_iter =	sock_read_iter,
	.write_iter =	sock_write_iter,
	.poll =		sock_poll,
	.unlocked_ioctl = sock_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = compat_sock_ioctl,
#endif
	.mmap =		sock_mmap,
	.release =	sock_close,
	.fasync =	sock_fasync,
	.sendpage =	sock_sendpage,
	.splice_write = generic_splice_sendpage,
	.splice_read =	sock_splice_read,
};

/*
 *      The protocol list. Each protocol is registered in here.
 */

static DEFINE_SPINLOCK(net_family_lock);

static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;

/*
 *      Statistics counters of the socket lists
 */

static DEFINE_PER_CPU(int, sockets_in_use);

/*
 * Support routines.
 * Move socket addresses back and forth across the kernel/user
 * divide and look after the messy bits.
 */

/**
 *      move_addr_to_kernel     -       copy a socket address into kernel space
 *      @uaddr: Address in user space
 *      @kaddr: Address in kernel space
 *      @ulen: Length in user space
 *
 *      The address is copied into kernel space. If the provided address is
 *      too long an error code of -EINVAL is returned. If the copy gives
 *      invalid addresses -EFAULT is returned. On a success 0 is returned.
 */


int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr) { if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) return -EINVAL; if (ulen == 0) return 0; if (copy_from_user(kaddr, uaddr, ulen)) return -EFAULT; return audit_sockaddr(ulen, kaddr); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git5479.41%233.33%
hideaki yoshifujihideaki yoshifuji68.82%116.67%
david woodhousedavid woodhouse68.82%116.67%
linus torvaldslinus torvalds11.47%116.67%
maciej zenczykowskimaciej zenczykowski11.47%116.67%
Total68100.00%6100.00%

/** * move_addr_to_user - copy an address to user space * @kaddr: kernel space address * @klen: length of address in kernel * @uaddr: user space address * @ulen: pointer to user length field * * The value pointed to by ulen on entry is the buffer length available. * This is overwritten with the buffer space used. -EINVAL is returned * if an overlong buffer is specified or a negative buffer size. -EFAULT * is returned if either the buffer or the length field are not * accessible. * After copying the data up to the limit the user specifies, the true * length of the data is written over the length limit the user * specified. Zero is returned for a success. */
static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, void __user *uaddr, int __user *ulen) { int err; int len; BUG_ON(klen > sizeof(struct sockaddr_storage)); err = get_user(len, ulen); if (err) return err; if (len > klen) len = klen; if (len < 0) return -EINVAL; if (len) { if (audit_sockaddr(klen, kaddr)) return -ENOMEM; if (copy_to_user(uaddr, kaddr, len)) return -EFAULT; } /* * "fromlen shall refer to the value before truncation.." * 1003.1g */ return __put_user(klen, ulen); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git8671.67%750.00%
steve grubbsteve grubb1310.83%17.14%
hannes frederic sowahannes frederic sowa119.17%17.14%
stephen hemmingerstephen hemminger65.00%214.29%
linus torvaldslinus torvalds21.67%17.14%
maciej zenczykowskimaciej zenczykowski10.83%17.14%
hideaki yoshifujihideaki yoshifuji10.83%17.14%
Total120100.00%14100.00%

static struct kmem_cache *sock_inode_cachep __read_mostly;
static struct inode *sock_alloc_inode(struct super_block *sb) { struct socket_alloc *ei; struct socket_wq *wq; ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); if (!ei) return NULL; wq = kmalloc(sizeof(*wq), GFP_KERNEL); if (!wq) { kmem_cache_free(sock_inode_cachep, ei); return NULL; } init_waitqueue_head(&wq->wait); wq->fasync_list = NULL; wq->flags = 0; RCU_INIT_POINTER(ei->socket.wq, wq); ei->socket.state = SS_UNCONNECTED; ei->socket.flags = 0; ei->socket.ops = NULL; ei->socket.sk = NULL; ei->socket.file = NULL; return &ei->vfs_inode; }

Contributors

PersonTokensPropCommitsCommitProp
eric dumazeteric dumazet5034.01%233.33%
al viroal viro4631.29%116.67%
petr vandrovec*petr vandrovec*4429.93%116.67%
nicolai stangenicolai stange64.08%116.67%
christoph lameterchristoph lameter10.68%116.67%
Total147100.00%6100.00%


static void sock_destroy_inode(struct inode *inode) { struct socket_alloc *ei; struct socket_wq *wq; ei = container_of(inode, struct socket_alloc, vfs_inode); wq = rcu_dereference_protected(ei->socket.wq, 1); kfree_rcu(wq, rcu); kmem_cache_free(sock_inode_cachep, ei); }

Contributors

PersonTokensPropCommitsCommitProp
eric dumazeteric dumazet3660.00%240.00%
al viroal viro2135.00%120.00%
lai jiangshanlai jiangshan23.33%120.00%
neil brownneil brown11.67%120.00%
Total60100.00%5100.00%


static void init_once(void *foo) { struct socket_alloc *ei = (struct socket_alloc *)foo; inode_init_once(&ei->vfs_inode); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro2790.00%150.00%
christoph lameterchristoph lameter310.00%150.00%
Total30100.00%2100.00%


static int init_inodecache(void) { sock_inode_cachep = kmem_cache_create("sock_inode_cache", sizeof(struct socket_alloc), 0, (SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD | SLAB_ACCOUNT), init_once); if (sock_inode_cachep == NULL) return -ENOMEM; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro4083.33%120.00%
paul jacksonpaul jackson48.33%240.00%
vladimir davydovvladimir davydov24.17%120.00%
andrew mortonandrew morton24.17%120.00%
Total48100.00%5100.00%

static const struct super_operations sockfs_ops = { .alloc_inode = sock_alloc_inode, .destroy_inode = sock_destroy_inode, .statfs = simple_statfs, }; /* * sockfs_dname() is called from d_path(). */
static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) { return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", d_inode(dentry)->i_ino); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro3592.11%150.00%
david howellsdavid howells37.89%150.00%
Total38100.00%2100.00%

static const struct dentry_operations sockfs_dentry_operations = { .d_dname = sockfs_dname, };
static struct dentry *sockfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { return mount_pseudo(fs_type, "socket:", &sockfs_ops, &sockfs_dentry_operations, SOCKFS_MAGIC); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro3892.68%466.67%
pre-gitpre-git24.88%116.67%
andries brouwerandries brouwer12.44%116.67%
Total41100.00%6100.00%

static struct vfsmount *sock_mnt __read_mostly; static struct file_system_type sock_fs_type = { .name = "sockfs", .mount = sockfs_mount, .kill_sb = kill_anon_super, }; /* * Obtains the first available file descriptor and sets it up for use. * * These functions create file structures and maps them to fd space * of the current process. On success it returns file descriptor * and file struct implicitly stored in sock->file. * Note that another thread may close file descriptor before we return * from this function. We use the fact that now we do not refer * to socket after mapping. If one day we will need it, this * function will increment ref. count on file by 1. * * In any case returned fd MAY BE not valid! * This race condition is unavoidable * with shared fd spaces, we cannot solve it inside kernel, * but we take care of internal coherence yet. */
struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) { struct qstr name = { .name = "" }; struct path path; struct file *file; if (dname) { name.name = dname; name.len = strlen(name.name); } else if (sock->sk) { name.name = sock->sk->sk_prot_creator->name; name.len = strlen(name.name); } path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); if (unlikely(!path.dentry)) return ERR_PTR(-ENOMEM); path.mnt = mntget(sock_mnt); d_instantiate(path.dentry, SOCK_INODE(sock)); file = alloc_file(&path, FMODE_READ | FMODE_WRITE, &socket_file_ops); if (IS_ERR(file)) { /* drop dentry, keep inode */ ihold(d_inode(path.dentry)); path_put(&path); return file; } sock->file = file; file->f_flags = O_RDWR | (flags & O_NONBLOCK); file->private_data = sock; return file; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro8237.61%625.00%
masatake yamatomasatake yamato6027.52%14.17%
pre-gitpre-git3516.06%625.00%
dave hansendave hansen94.13%14.17%
david s. millerdavid s. miller83.67%14.17%
ulrich drepperulrich drepper83.67%28.33%
benjamin lahaisebenjamin lahaise41.83%14.17%
josef sipekjosef sipek31.38%14.17%
anatol pomozovanatol pomozov31.38%14.17%
david howellsdavid howells31.38%14.17%
eric dumazeteric dumazet20.92%28.33%
nick pigginnick piggin10.46%14.17%
Total218100.00%24100.00%

EXPORT_SYMBOL(sock_alloc_file);
static int sock_map_fd(struct socket *sock, int flags) { struct file *newfile; int fd = get_unused_fd_flags(flags); if (unlikely(fd < 0)) return fd; newfile = sock_alloc_file(sock, flags, NULL); if (likely(!IS_ERR(newfile))) { fd_install(fd, newfile); return fd; } put_unused_fd(fd); return PTR_ERR(newfile); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro3946.43%333.33%
david s. millerdavid s. miller2630.95%111.11%
pre-gitpre-git1011.90%222.22%
ulrich drepperulrich drepper44.76%111.11%
eric dumazeteric dumazet33.57%111.11%
masatake yamatomasatake yamato22.38%111.11%
Total84100.00%9100.00%


struct socket *sock_from_file(struct file *file, int *err) { if (file->f_op == &socket_file_ops) return file->private_data; /* set in sock_map_fd */ *err = -ENOTSOCK; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git2255.00%360.00%
benjamin lahaisebenjamin lahaise1845.00%240.00%
Total40100.00%5100.00%

EXPORT_SYMBOL(sock_from_file); /** * sockfd_lookup - Go from a file number to its socket slot * @fd: file handle * @err: pointer to an error code return * * The file handle passed in is locked and the socket it is bound * too is returned. If an error occurs the err pointer is overwritten * with a negative errno code and NULL is returned. The function checks * for both invalid handles and passing a handle which is not a socket. * * On a success the socket object pointer is returned. */
struct socket *sockfd_lookup(int fd, int *err) { struct file *file; struct socket *sock; file = fget(fd); if (!file) { *err = -EBADF; return NULL; } sock = sock_from_file(file, err); if (!sock) fput(file); return sock; }

Contributors

PersonTokensPropCommitsCommitProp
benjamin lahaisebenjamin lahaise6492.75%150.00%
stephen hemmingerstephen hemminger57.25%150.00%
Total69100.00%2100.00%

EXPORT_SYMBOL(sockfd_lookup);
static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) { struct fd f = fdget(fd); struct socket *sock; *err = -EBADF; if (f.file) { sock = sock_from_file(f.file, err); if (likely(sock)) { *fput_needed = f.flags; return sock; } fdput(f); } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
benjamin lahaisebenjamin lahaise5463.53%133.33%
al viroal viro2529.41%133.33%
hua zhonghua zhong67.06%133.33%
Total85100.00%3100.00%

#define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname" #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX) #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
static ssize_t sockfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *value, size_t size) { const char *proto_name; size_t proto_size; int error; error = -ENODATA; if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) { proto_name = dentry->d_name.name; proto_size = strlen(proto_name); if (value) { error = -ERANGE; if (proto_size + 1 > size) goto out; strncpy(value, proto_name, proto_size + 1); } error = proto_size + 1; } out: return error; }

Contributors

PersonTokensPropCommitsCommitProp
masatake yamatomasatake yamato11295.73%150.00%
al viroal viro54.27%150.00%
Total117100.00%2100.00%


static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, size_t size) { ssize_t len; ssize_t used = 0; len = security_inode_listsecurity(d_inode(dentry), buffer, size); if (len < 0) return len; used += len; if (buffer) { if (size < used) return -ERANGE; buffer += len; } len = (XATTR_NAME_SOCKPROTONAME_LEN + 1); used += len; if (buffer) { if (size < used) return -ERANGE; memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len); buffer += len; } return used; }

Contributors

PersonTokensPropCommitsCommitProp
masatake yamatomasatake yamato11497.44%150.00%
david howellsdavid howells32.56%150.00%
Total117100.00%2100.00%

static const struct inode_operations sockfs_inode_ops = { .getxattr = sockfs_getxattr, .listxattr = sockfs_listxattr, }; /** * sock_alloc - allocate a socket * * Allocate a new inode and socket object. The two are bound together * and initialised. The socket is then returned. If we are out of inodes * NULL is returned. */
struct socket *sock_alloc(void) { struct inode *inode; struct socket *sock; inode = new_inode_pseudo(sock_mnt->mnt_sb); if (!inode) return NULL; sock = SOCKET_I(inode); kmemcheck_annotate_bitfield(sock, type); inode->i_ino = get_next_ino(); inode->i_mode = S_IFSOCK | S_IRWXUGO; inode->i_uid = current_fsuid(); inode->i_gid = current_fsgid(); inode->i_op = &sockfs_inode_ops; this_cpu_add(sockets_in_use, 1); return sock; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git5759.38%533.33%
eric dumazeteric dumazet1010.42%320.00%
christoph hellwigchristoph hellwig77.29%16.67%
masatake yamatomasatake yamato77.29%16.67%
linus torvaldslinus torvalds55.21%16.67%
ravikiran g thirumalairavikiran g thirumalai44.17%16.67%
david howellsdavid howells44.17%16.67%
al viroal viro11.04%16.67%
alex shialex shi11.04%16.67%
Total96100.00%15100.00%

EXPORT_SYMBOL(sock_alloc); /** * sock_release - close a socket * @sock: socket to close * * The socket is released from the protocol stack if it has a release * callback, and the inode is then released if the socket is bound to * an inode not a file. */
void sock_release(struct socket *sock) { if (sock->ops) { struct module *owner = sock->ops->owner; sock->ops->release(sock); sock->ops = NULL; module_put(owner); } if (rcu_dereference_protected(sock->wq, 1)->fasync_list) pr_err("%s: fasync list not empty!\n", __func__); this_cpu_sub(sockets_in_use, 1); if (!sock->file) { iput(SOCK_INODE(sock)); return; } sock->file = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git5555.00%430.77%
arnaldo carvalho de meloarnaldo carvalho de melo2424.00%215.38%
eric dumazeteric dumazet99.00%323.08%
yang yingliangyang yingliang44.00%17.69%
ravikiran g thirumalairavikiran g thirumalai44.00%17.69%
al viroal viro33.00%17.69%
alex shialex shi11.00%17.69%
Total100100.00%13100.00%

EXPORT_SYMBOL(sock_release);
void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) { u8 flags = *tx_flags; if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE) flags |= SKBTX_HW_TSTAMP; if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) flags |= SKBTX_SW_TSTAMP; if (tsflags & SOF_TIMESTAMPING_TX_SCHED) flags |= SKBTX_SCHED_TSTAMP; *tx_flags = flags; }

Contributors

PersonTokensPropCommitsCommitProp
patrick ohlypatrick ohly1426.42%111.11%
eric dumazeteric dumazet1222.64%111.11%
willem de bruijnwillem de bruijn1120.75%333.33%
oliver hartkoppoliver hartkopp815.09%111.11%
soheil hassas yeganehsoheil hassas yeganeh59.43%111.11%
johannes bergjohannes berg23.77%111.11%
daniel borkmanndaniel borkmann11.89%111.11%
Total53100.00%9100.00%

EXPORT_SYMBOL(__sock_tx_timestamp);
static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) { int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg)); BUG_ON(ret == -EIOCBQUEUED); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro1838.30%222.22%
pre-gitpre-git1327.66%333.33%
anton blanchardanton blanchard1327.66%111.11%
benjamin lahaisebenjamin lahaise24.26%222.22%
ying xueying xue12.13%111.11%
Total47100.00%9100.00%


int sock_sendmsg(struct socket *sock, struct msghdr *msg) { int err = security_socket_sendmsg(sock, msg, msg_data_left(msg)); return err ?: sock_sendmsg_nosec(sock, msg); }

Contributors

PersonTokensPropCommitsCommitProp
anton blanchardanton blanchard1843.90%114.29%
james morrisjames morris921.95%114.29%
gu zhenggu zheng717.07%114.29%
al viroal viro49.76%228.57%
ying xueying xue24.88%114.29%
pre-gitpre-git12.44%114.29%
Total41100.00%7100.00%

EXPORT_SYMBOL(sock_sendmsg);
int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t size) { iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size); return sock_sendmsg(sock, msg); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro52100.00%3100.00%
Total52100.00%3100.00%

EXPORT_SYMBOL(kernel_sendmsg); /* * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) */
void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) { int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); struct scm_timestamping tss; int empty = 1; struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); /* Race occurred between timestamp enabling and packet receiving. Fill in the current time for now. */ if (need_software_tstamp && skb->tstamp.tv64 == 0) __net_timestamp(skb); if (need_software_tstamp) { if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { struct timeval tv; skb_get_timestamp(skb, &tv); put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv); } else { struct timespec ts; skb_get_timestampns(skb, &ts); put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts); } } memset(&tss, 0, sizeof(tss)); if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) empty = 0; if (shhwtstamps && (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) empty = 0; if (!empty) put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING, sizeof(tss), &tss); }

Contributors

PersonTokensPropCommitsCommitProp
patrick ohlypatrick ohly12050.63%120.00%
eric dumazeteric dumazet8435.44%120.00%
willem de bruijnwillem de bruijn2711.39%240.00%
daniel borkmanndaniel borkmann62.53%120.00%
Total237100.00%5100.00%

EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) { int ack; if (!sock_flag(sk, SOCK_WIFI_STATUS)) return; if (!skb->wifi_acked_valid) return; ack = skb->wifi_acked; put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack); }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg65100.00%1100.00%
Total65100.00%1100.00%

EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) { if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount) put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount); }

Contributors

PersonTokensPropCommitsCommitProp
neil hormanneil horman5588.71%133.33%
eyal birgereyal birger69.68%133.33%
stephen hemmingerstephen hemminger11.61%133.33%
Total62100.00%3100.00%


void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) { sock_recv_timestamp(msg, sk, skb); sock_recv_drops(msg, sk, skb); }

Contributors

PersonTokensPropCommitsCommitProp
neil hormanneil horman3797.37%150.00%
eric dumazeteric dumazet12.63%150.00%
Total38100.00%2100.00%

EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, int flags) { return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo1641.03%116.67%
pre-gitpre-git1538.46%116.67%
al viroal viro410.26%116.67%
benjamin lahaisebenjamin lahaise37.69%233.33%
ying xueying xue12.56%116.67%
Total39100.00%6100.00%


int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags) { int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags); return err ?: sock_recvmsg_nosec(sock, msg, flags); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo2143.75%120.00%
james morrisjames morris1225.00%120.00%
pre-gitpre-git918.75%120.00%
al viroal viro48.33%120.00%
ying xueying xue24.17%120.00%
Total48100.00%5100.00%

EXPORT_SYMBOL(sock_recvmsg); /** * kernel_recvmsg - Receive a message from a socket (kernel space) * @sock: The socket to receive the message from * @msg: Received message * @vec: Input s/g array for message data * @num: Size of input s/g array * @size: Number of bytes to read * @flags: Message flags (MSG_DONTWAIT, etc...) * * On return the msg structure contains the scatter/gather array passed in the * vec argument. The array is modified so that it consists of the unfilled * portion of the original array. * * The returned value is the total number of bytes received, or an error. */
int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t size, int flags) { mm_segment_t oldfs = get_fs(); int result; iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size); set_fs(KERNEL_DS); result = sock_recvmsg(sock, msg,