cregit-Linux how code gets into the kernel

Release 4.14 net/core/sock.c

Directory: net/core
/*
 * INET         An implementation of the TCP/IP protocol suite for the LINUX
 *              operating system.  INET is implemented using the  BSD Socket
 *              interface as the means of communication with the user level.
 *
 *              Generic socket support routines. Memory allocators, socket lock/release
 *              handler for protocols to use and generic option handler.
 *
 *
 * Authors:     Ross Biro
 *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 *              Florian La Roche, <flla@stud.uni-sb.de>
 *              Alan Cox, <A.Cox@swansea.ac.uk>
 *
 * Fixes:
 *              Alan Cox        :       Numerous verify_area() problems
 *              Alan Cox        :       Connecting on a connecting socket
 *                                      now returns an error for tcp.
 *              Alan Cox        :       sock->protocol is set correctly.
 *                                      and is not sometimes left as 0.
 *              Alan Cox        :       connect handles icmp errors on a
 *                                      connect properly. Unfortunately there
 *                                      is a restart syscall nasty there. I
 *                                      can't match BSD without hacking the C
 *                                      library. Ideas urgently sought!
 *              Alan Cox        :       Disallow bind() to addresses that are
 *                                      not ours - especially broadcast ones!!
 *              Alan Cox        :       Socket 1024 _IS_ ok for users. (fencepost)
 *              Alan Cox        :       sock_wfree/sock_rfree don't destroy sockets,
 *                                      instead they leave that for the DESTROY timer.
 *              Alan Cox        :       Clean up error flag in accept
 *              Alan Cox        :       TCP ack handling is buggy, the DESTROY timer
 *                                      was buggy. Put a remove_sock() in the handler
 *                                      for memory when we hit 0. Also altered the timer
 *                                      code. The ACK stuff can wait and needs major
 *                                      TCP layer surgery.
 *              Alan Cox        :       Fixed TCP ack bug, removed remove sock
 *                                      and fixed timer/inet_bh race.
 *              Alan Cox        :       Added zapped flag for TCP
 *              Alan Cox        :       Move kfree_skb into skbuff.c and tidied up surplus code
 *              Alan Cox        :       for new sk_buff allocations wmalloc/rmalloc now call alloc_skb
 *              Alan Cox        :       kfree_s calls now are kfree_skbmem so we can track skb resources
 *              Alan Cox        :       Supports socket option broadcast now as does udp. Packet and raw need fixing.
 *              Alan Cox        :       Added RCVBUF,SNDBUF size setting. It suddenly occurred to me how easy it was so...
 *              Rick Sladkey    :       Relaxed UDP rules for matching packets.
 *              C.E.Hawkins     :       IFF_PROMISC/SIOCGHWADDR support
 *      Pauline Middelink       :       identd support
 *              Alan Cox        :       Fixed connect() taking signals I think.
 *              Alan Cox        :       SO_LINGER supported
 *              Alan Cox        :       Error reporting fixes
 *              Anonymous       :       inet_create tidied up (sk->reuse setting)
 *              Alan Cox        :       inet sockets don't set sk->type!
 *              Alan Cox        :       Split socket option code
 *              Alan Cox        :       Callbacks
 *              Alan Cox        :       Nagle flag for Charles & Johannes stuff
 *              Alex            :       Removed restriction on inet fioctl
 *              Alan Cox        :       Splitting INET from NET core
 *              Alan Cox        :       Fixed bogus SO_TYPE handling in getsockopt()
 *              Adam Caldwell   :       Missing return in SO_DONTROUTE/SO_DEBUG code
 *              Alan Cox        :       Split IP from generic code
 *              Alan Cox        :       New kfree_skbmem()
 *              Alan Cox        :       Make SO_DEBUG superuser only.
 *              Alan Cox        :       Allow anyone to clear SO_DEBUG
 *                                      (compatibility fix)
 *              Alan Cox        :       Added optimistic memory grabbing for AF_UNIX throughput.
 *              Alan Cox        :       Allocator for a socket is settable.
 *              Alan Cox        :       SO_ERROR includes soft errors.
 *              Alan Cox        :       Allow NULL arguments on some SO_ opts
 *              Alan Cox        :       Generic socket allocation to make hooks
 *                                      easier (suggested by Craig Metz).
 *              Michael Pall    :       SO_ERROR returns positive errno again
 *              Steve Whitehouse:       Added default destructor to free
 *                                      protocol private data.
 *              Steve Whitehouse:       Added various other default routines
 *                                      common to several socket families.
 *              Chris Evans     :       Call suser() check last on F_SETOWN
 *              Jay Schulist    :       Added SO_ATTACH_FILTER and SO_DETACH_FILTER.
 *              Andi Kleen      :       Add sock_kmalloc()/sock_kfree_s()
 *              Andi Kleen      :       Fix write_space callback
 *              Chris Evans     :       Security fixes - signedness again
 *              Arnaldo C. Melo :       cleanups, use skb_queue_purge
 *
 * To Fix:
 *
 *
 *              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.
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/errqueue.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/tcp.h>
#include <linux/init.h>
#include <linux/highmem.h>
#include <linux/user_namespace.h>
#include <linux/static_key.h>
#include <linux/memcontrol.h>
#include <linux/prefetch.h>

#include <linux/uaccess.h>

#include <linux/netdevice.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
#include <net/net_namespace.h>
#include <net/request_sock.h>
#include <net/sock.h>
#include <linux/net_tstamp.h>
#include <net/xfrm.h>
#include <linux/ipsec.h>
#include <net/cls_cgroup.h>
#include <net/netprio_cgroup.h>
#include <linux/sock_diag.h>

#include <linux/filter.h>
#include <net/sock_reuseport.h>

#include <trace/events/sock.h>

#include <net/tcp.h>
#include <net/busy_poll.h>

static DEFINE_MUTEX(proto_list_mutex);
static LIST_HEAD(proto_list);

/**
 * sk_ns_capable - General socket capability test
 * @sk: Socket to use a capability on or through
 * @user_ns: The user namespace of the capability to use
 * @cap: The capability to use
 *
 * Test to see if the opener of the socket had when the socket was
 * created and the current process has the capability @cap in the user
 * namespace @user_ns.
 */

bool sk_ns_capable(const struct sock *sk, struct user_namespace *user_ns, int cap) { return file_ns_capable(sk->sk_socket->file, user_ns, cap) && ns_capable(user_ns, cap); }

Contributors

PersonTokensPropCommitsCommitProp
Eric W. Biedermann40100.00%1100.00%
Total40100.00%1100.00%

EXPORT_SYMBOL(sk_ns_capable); /** * sk_capable - Socket global capability test * @sk: Socket to use a capability on or through * @cap: The global capability to use * * Test to see if the opener of the socket had when the socket was * created and the current process has the capability @cap in all user * namespaces. */
bool sk_capable(const struct sock *sk, int cap) { return sk_ns_capable(sk, &init_user_ns, cap); }

Contributors

PersonTokensPropCommitsCommitProp
Eric W. Biedermann25100.00%1100.00%
Total25100.00%1100.00%

EXPORT_SYMBOL(sk_capable); /** * sk_net_capable - Network namespace socket capability test * @sk: Socket to use a capability on or through * @cap: The capability to use * * Test to see if the opener of the socket had when the socket was created * and the current process has the capability @cap over the network namespace * the socket is a member of. */
bool sk_net_capable(const struct sock *sk, int cap) { return sk_ns_capable(sk, sock_net(sk)->user_ns, cap); }

Contributors

PersonTokensPropCommitsCommitProp
Eric W. Biedermann29100.00%1100.00%
Total29100.00%1100.00%

EXPORT_SYMBOL(sk_net_capable); /* * Each address family might have different locking rules, so we have * one slock key per address family and separate keys for internal and * userspace sockets. */ static struct lock_class_key af_family_keys[AF_MAX]; static struct lock_class_key af_family_kern_keys[AF_MAX]; static struct lock_class_key af_family_slock_keys[AF_MAX]; static struct lock_class_key af_family_kern_slock_keys[AF_MAX]; /* * Make lock validator output more readable. (we pre-construct these * strings build-time, so that runtime initialization of socket * locks is fast): */ #define _sock_locks(x) \ x "AF_UNSPEC", x "AF_UNIX" , x "AF_INET" , \ x "AF_AX25" , x "AF_IPX" , x "AF_APPLETALK", \ x "AF_NETROM", x "AF_BRIDGE" , x "AF_ATMPVC" , \ x "AF_X25" , x "AF_INET6" , x "AF_ROSE" , \ x "AF_DECnet", x "AF_NETBEUI" , x "AF_SECURITY" , \ x "AF_KEY" , x "AF_NETLINK" , x "AF_PACKET" , \ x "AF_ASH" , x "AF_ECONET" , x "AF_ATMSVC" , \ x "AF_RDS" , x "AF_SNA" , x "AF_IRDA" , \ x "AF_PPPOX" , x "AF_WANPIPE" , x "AF_LLC" , \ x "27" , x "28" , x "AF_CAN" , \ x "AF_TIPC" , x "AF_BLUETOOTH", x "IUCV" , \ x "AF_RXRPC" , x "AF_ISDN" , x "AF_PHONET" , \ x "AF_IEEE802154", x "AF_CAIF" , x "AF_ALG" , \ x "AF_NFC" , x "AF_VSOCK" , x "AF_KCM" , \ x "AF_QIPCRTR", x "AF_SMC" , x "AF_MAX" static const char *const af_family_key_strings[AF_MAX+1] = { _sock_locks("sk_lock-") }; static const char *const af_family_slock_key_strings[AF_MAX+1] = { _sock_locks("slock-") }; static const char *const af_family_clock_key_strings[AF_MAX+1] = { _sock_locks("clock-") }; static const char *const af_family_kern_key_strings[AF_MAX+1] = { _sock_locks("k-sk_lock-") }; static const char *const af_family_kern_slock_key_strings[AF_MAX+1] = { _sock_locks("k-slock-") }; static const char *const af_family_kern_clock_key_strings[AF_MAX+1] = { _sock_locks("k-clock-") }; static const char *const af_family_rlock_key_strings[AF_MAX+1] = { "rlock-AF_UNSPEC", "rlock-AF_UNIX" , "rlock-AF_INET" , "rlock-AF_AX25" , "rlock-AF_IPX" , "rlock-AF_APPLETALK", "rlock-AF_NETROM", "rlock-AF_BRIDGE" , "rlock-AF_ATMPVC" , "rlock-AF_X25" , "rlock-AF_INET6" , "rlock-AF_ROSE" , "rlock-AF_DECnet", "rlock-AF_NETBEUI" , "rlock-AF_SECURITY" , "rlock-AF_KEY" , "rlock-AF_NETLINK" , "rlock-AF_PACKET" , "rlock-AF_ASH" , "rlock-AF_ECONET" , "rlock-AF_ATMSVC" , "rlock-AF_RDS" , "rlock-AF_SNA" , "rlock-AF_IRDA" , "rlock-AF_PPPOX" , "rlock-AF_WANPIPE" , "rlock-AF_LLC" , "rlock-27" , "rlock-28" , "rlock-AF_CAN" , "rlock-AF_TIPC" , "rlock-AF_BLUETOOTH", "rlock-AF_IUCV" , "rlock-AF_RXRPC" , "rlock-AF_ISDN" , "rlock-AF_PHONET" , "rlock-AF_IEEE802154", "rlock-AF_CAIF" , "rlock-AF_ALG" , "rlock-AF_NFC" , "rlock-AF_VSOCK" , "rlock-AF_KCM" , "rlock-AF_QIPCRTR", "rlock-AF_SMC" , "rlock-AF_MAX" }; static const char *const af_family_wlock_key_strings[AF_MAX+1] = { "wlock-AF_UNSPEC", "wlock-AF_UNIX" , "wlock-AF_INET" , "wlock-AF_AX25" , "wlock-AF_IPX" , "wlock-AF_APPLETALK", "wlock-AF_NETROM", "wlock-AF_BRIDGE" , "wlock-AF_ATMPVC" , "wlock-AF_X25" , "wlock-AF_INET6" , "wlock-AF_ROSE" , "wlock-AF_DECnet", "wlock-AF_NETBEUI" , "wlock-AF_SECURITY" , "wlock-AF_KEY" , "wlock-AF_NETLINK" , "wlock-AF_PACKET" , "wlock-AF_ASH" , "wlock-AF_ECONET" , "wlock-AF_ATMSVC" , "wlock-AF_RDS" , "wlock-AF_SNA" , "wlock-AF_IRDA" , "wlock-AF_PPPOX" , "wlock-AF_WANPIPE" , "wlock-AF_LLC" , "wlock-27" , "wlock-28" , "wlock-AF_CAN" , "wlock-AF_TIPC" , "wlock-AF_BLUETOOTH", "wlock-AF_IUCV" , "wlock-AF_RXRPC" , "wlock-AF_ISDN" , "wlock-AF_PHONET" , "wlock-AF_IEEE802154", "wlock-AF_CAIF" , "wlock-AF_ALG" , "wlock-AF_NFC" , "wlock-AF_VSOCK" , "wlock-AF_KCM" , "wlock-AF_QIPCRTR", "wlock-AF_SMC" , "wlock-AF_MAX" }; static const char *const af_family_elock_key_strings[AF_MAX+1] = { "elock-AF_UNSPEC", "elock-AF_UNIX" , "elock-AF_INET" , "elock-AF_AX25" , "elock-AF_IPX" , "elock-AF_APPLETALK", "elock-AF_NETROM", "elock-AF_BRIDGE" , "elock-AF_ATMPVC" , "elock-AF_X25" , "elock-AF_INET6" , "elock-AF_ROSE" , "elock-AF_DECnet", "elock-AF_NETBEUI" , "elock-AF_SECURITY" , "elock-AF_KEY" , "elock-AF_NETLINK" , "elock-AF_PACKET" , "elock-AF_ASH" , "elock-AF_ECONET" , "elock-AF_ATMSVC" , "elock-AF_RDS" , "elock-AF_SNA" , "elock-AF_IRDA" , "elock-AF_PPPOX" , "elock-AF_WANPIPE" , "elock-AF_LLC" , "elock-27" , "elock-28" , "elock-AF_CAN" , "elock-AF_TIPC" , "elock-AF_BLUETOOTH", "elock-AF_IUCV" , "elock-AF_RXRPC" , "elock-AF_ISDN" , "elock-AF_PHONET" , "elock-AF_IEEE802154", "elock-AF_CAIF" , "elock-AF_ALG" , "elock-AF_NFC" , "elock-AF_VSOCK" , "elock-AF_KCM" , "elock-AF_QIPCRTR", "elock-AF_SMC" , "elock-AF_MAX" }; /* * sk_callback_lock and sk queues locking rules are per-address-family, * so split the lock classes by using a per-AF key: */ static struct lock_class_key af_callback_keys[AF_MAX]; static struct lock_class_key af_rlock_keys[AF_MAX]; static struct lock_class_key af_wlock_keys[AF_MAX]; static struct lock_class_key af_elock_keys[AF_MAX]; static struct lock_class_key af_kern_callback_keys[AF_MAX]; /* Run time adjustable parameters. */ __u32 sysctl_wmem_max __read_mostly = SK_WMEM_MAX; EXPORT_SYMBOL(sysctl_wmem_max); __u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX; EXPORT_SYMBOL(sysctl_rmem_max); __u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; /* Maximal space eaten by iovec or ancillary data plus some space */ int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); EXPORT_SYMBOL(sysctl_optmem_max); int sysctl_tstamp_allow_data __read_mostly = 1; struct static_key memalloc_socks = STATIC_KEY_INIT_FALSE; EXPORT_SYMBOL_GPL(memalloc_socks); /** * sk_set_memalloc - sets %SOCK_MEMALLOC * @sk: socket to set it on * * Set %SOCK_MEMALLOC on a socket for access to emergency reserves. * It's the responsibility of the admin to adjust min_free_kbytes * to meet the requirements */
void sk_set_memalloc(struct sock *sk) { sock_set_flag(sk, SOCK_MEMALLOC); sk->sk_allocation |= __GFP_MEMALLOC; static_key_slow_inc(&memalloc_socks); }

Contributors

PersonTokensPropCommitsCommitProp
Mel Gorman29100.00%2100.00%
Total29100.00%2100.00%

EXPORT_SYMBOL_GPL(sk_set_memalloc);
void sk_clear_memalloc(struct sock *sk) { sock_reset_flag(sk, SOCK_MEMALLOC); sk->sk_allocation &= ~__GFP_MEMALLOC; static_key_slow_dec(&memalloc_socks); /* * SOCK_MEMALLOC is allowed to ignore rmem limits to ensure forward * progress of swapping. SOCK_MEMALLOC may be cleared while * it has rmem allocations due to the last swapfile being deactivated * but there is a risk that the socket is unusable due to exceeding * the rmem limits. Reclaim the reserves and obey rmem limits again. */ sk_mem_reclaim(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Mel Gorman36100.00%4100.00%
Total36100.00%4100.00%

EXPORT_SYMBOL_GPL(sk_clear_memalloc);
int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) { int ret; unsigned int noreclaim_flag; /* these should have been dropped before queueing */ BUG_ON(!sock_flag(sk, SOCK_MEMALLOC)); noreclaim_flag = memalloc_noreclaim_save(); ret = sk->sk_backlog_rcv(sk, skb); memalloc_noreclaim_restore(noreclaim_flag); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Mel Gorman5086.21%150.00%
Vlastimil Babka813.79%150.00%
Total58100.00%2100.00%

EXPORT_SYMBOL(__sk_backlog_rcv);
static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen) { struct timeval tv; if (optlen < sizeof(tv)) return -EINVAL; if (copy_from_user(&tv, optval, sizeof(tv))) return -EFAULT; if (tv.tv_usec < 0 || tv.tv_usec >= USEC_PER_SEC) return -EDOM; if (tv.tv_sec < 0) { static int warned __read_mostly; *timeo_p = 0; if (warned < 10 && net_ratelimit()) { warned++; pr_info("%s: `%s' (pid %d) tries to set negative timeout\n", __func__, current->comm, task_pid_nr(current)); } return 0; } *timeo_p = MAX_SCHEDULE_TIMEOUT; if (tv.tv_sec == 0 && tv.tv_usec == 0) return 0; if (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT/HZ - 1)) *timeo_p = tv.tv_sec * HZ + DIV_ROUND_UP(tv.tv_usec, USEC_PER_SEC / HZ); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)10758.15%112.50%
Vasily Averin6133.15%112.50%
Gao Feng52.72%112.50%
Joe Perches42.17%112.50%
Pavel Emelyanov31.63%112.50%
Ilpo Järvinen21.09%112.50%
Linus Torvalds10.54%112.50%
Andrew Morton10.54%112.50%
Total184100.00%8100.00%


static void sock_warn_obsolete_bsdism(const char *name) { static int warned; static char warncomm[TASK_COMM_LEN]; if (strcmp(warncomm, current->comm) && warned < 5) { strcpy(warncomm, current->comm); pr_warn("process `%s' is using obsolete %s SO_BSDCOMPAT\n", warncomm, name); warned++; } }

Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen4066.67%125.00%
James Morris1728.33%125.00%
Joe Perches23.33%125.00%
Hideaki Yoshifuji / 吉藤英明11.67%125.00%
Total60100.00%4100.00%


static bool sock_needs_netstamp(const struct sock *sk) { switch (sk->sk_family) { case AF_UNSPEC: case AF_UNIX: return false; default: return true; } }

Contributors

PersonTokensPropCommitsCommitProp
Hannes Frederic Sowa33100.00%1100.00%
Total33100.00%1100.00%


static void sock_disable_timestamp(struct sock *sk, unsigned long flags) { if (sk->sk_flags & flags) { sk->sk_flags &= ~flags; if (sock_needs_netstamp(sk) && !(sk->sk_flags & SK_FLAGS_TIMESTAMP)) net_disable_timestamp(); } }

Contributors

PersonTokensPropCommitsCommitProp
Christoph Hellwig2039.22%120.00%
Eric Dumazet1835.29%120.00%
Patrick Ohly611.76%120.00%
Hannes Frederic Sowa59.80%120.00%
Patrick McHardy23.92%120.00%
Total51100.00%5100.00%


int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { unsigned long flags; struct sk_buff_head *list = &sk->sk_receive_queue; if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) { atomic_inc(&sk->sk_drops); trace_sock_rcvqueue_full(sk, skb); return -ENOMEM; } if (!sk_rmem_schedule(sk, skb, skb->truesize)) { atomic_inc(&sk->sk_drops); return -ENOBUFS; } skb->dev = NULL; skb_set_owner_r(skb, sk); /* we escape from rcu protected region, make sure we dont leak * a norefcounted dst */ skb_dst_force(skb); spin_lock_irqsave(&list->lock, flags); sock_skb_set_dropcount(sk, skb); __skb_queue_tail(list, skb); spin_unlock_irqrestore(&list->lock, flags); if (!sock_flag(sk, SOCK_DEAD)) sk->sk_data_ready(sk); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Denys Vlasenko7042.42%111.11%
Neil Horman3923.64%111.11%
Eric Dumazet2716.36%222.22%
Hideo Aoki169.70%111.11%
Satoru Moriya74.24%111.11%
Eyal Birger31.82%111.11%
Mel Gorman21.21%111.11%
samanthakumar10.61%111.11%
Total165100.00%9100.00%

EXPORT_SYMBOL(__sock_queue_rcv_skb);
int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { int err; err = sk_filter(sk, skb); if (err) return err; return __sock_queue_rcv_skb(sk, skb); }

Contributors

PersonTokensPropCommitsCommitProp
samanthakumar42100.00%1100.00%
Total42100.00%1100.00%

EXPORT_SYMBOL(sock_queue_rcv_skb);
int __sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested, unsigned int trim_cap, bool refcounted) { int rc = NET_RX_SUCCESS; if (sk_filter_trim_cap(sk, skb, trim_cap)) goto discard_and_relse; skb->dev = NULL; if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { atomic_inc(&sk->sk_drops); goto discard_and_relse; } if (nested) bh_lock_sock_nested(sk); else bh_lock_sock(sk); if (!sock_owned_by_user(sk)) { /* * trylock + unlock semantics: */ mutex_acquire(&sk->sk_lock.dep_map, 0, 1, _RET_IP_); rc = sk_backlog_rcv(sk, skb); mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_); } else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) { bh_unlock_sock(sk); atomic_inc(&sk->sk_drops); goto discard_and_relse; } bh_unlock_sock(sk); out: if (refcounted) sock_put(sk); return rc; discard_and_relse: kfree_skb(skb); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
Denys Vlasenko8944.28%111.11%
Eric Dumazet3517.41%333.33%
Ingo Molnar3316.42%111.11%
Yi Zhu2210.95%222.22%
Arnaldo Carvalho de Melo146.97%111.11%
Willem de Bruijn83.98%111.11%
Total201100.00%9100.00%

EXPORT_SYMBOL(__sk_receive_skb);
struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) { struct dst_entry *dst = __sk_dst_get(sk); if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) { sk_tx_queue_clear(sk); sk->sk_dst_pending_confirm = 0; RCU_INIT_POINTER(sk->sk_dst_cache, NULL); dst_release(dst); return NULL; } return dst; }

Contributors

PersonTokensPropCommitsCommitProp
Denys Vlasenko6177.22%120.00%
Eric Dumazet67.59%120.00%
Julian Anastasov67.59%120.00%
Krishna Kumar56.33%120.00%
Stephen Hemminger11.27%120.00%
Total79100.00%5100.00%

EXPORT_SYMBOL(__sk_dst_check);
struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie) { struct dst_entry *dst = sk_dst_get(sk); if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) { sk_dst_reset(sk); dst_release(dst); return NULL; } return dst; }

Contributors

PersonTokensPropCommitsCommitProp
Denys Vlasenko64100.00%1100.00%
Total64100.00%1100.00%

EXPORT_SYMBOL(sk_dst_check);
static int sock_setbindtodevice(struct sock *sk, char __user *optval, int optlen) { int ret = -ENOPROTOOPT; #ifdef CONFIG_NETDEVICES struct net *net = sock_net(sk); char devname[IFNAMSIZ]; int index; /* Sorry... */ ret = -EPERM; if (!ns_capable(net->user_ns, CAP_NET_RAW)) goto out; ret = -EINVAL; if (optlen < 0) goto out; /* Bind this socket to a particular device like "eth0", * as specified in the passed interface name. If the * name is "" or the option length is zero the socket * is not bound. */ if (optlen > IFNAMSIZ - 1) optlen = IFNAMSIZ - 1; memset(devname, 0, sizeof(devname)); ret = -EFAULT; if (copy_from_user(devname, optval, optlen)) goto out; index = 0; if (devname[0] != '\0') { struct net_device *dev; rcu_read_lock(); dev = dev_get_by_name_rcu(net, devname); if (dev) index = dev->ifindex; rcu_read_unlock(); ret = -ENODEV; if (!dev) goto out; } lock_sock(sk); sk->sk_bound_dev_if = index; sk_dst_reset(sk); release_sock(sk); ret = 0; out: #endif return ret; }

Contributors

PersonTokensPropCommitsCommitProp
David S. Miller17982.11%228.57%
Eric Dumazet219.63%114.29%
Eric W. Biedermann146.42%228.57%
Hideaki Yoshifuji / 吉藤英明31.38%114.29%
Brian Haley10.46%114.29%
Total218100.00%7100.00%


static int sock_getbindtodevice(struct sock *sk, char __user *optval, int __user *optlen, int len) { int ret = -ENOPROTOOPT; #ifdef CONFIG_NETDEVICES struct net *net = sock_net(sk); char devname[IFNAMSIZ]; if (sk->sk_bound_dev_if == 0) { len = 0; goto zero; } ret = -EINVAL; if (len < IFNAMSIZ) goto out; ret = netdev_get_name(net, devname, sk->sk_bound_dev_if); if (ret) goto out; len = strlen(devname) + 1; ret = -EFAULT; if (copy_to_user(optval, devname, len)) goto out; zero: ret = -EFAULT; if (put_user(len, optlen)) goto out; ret = 0; out: #endif return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Brian Haley15396.84%150.00%
Nicolas Schichan53.16%150.00%
Total158100.00%2100.00%


static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool) { if (valbool) sock_set_flag(sk, bit); else sock_reset_flag(sk, bit); }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov37100.00%1100.00%
Total37100.00%1100.00%


bool sk_mc_loop(struct sock *sk) { if (dev_recursion_level()) return false; if (!sk) return true; switch (sk->sk_family) { case AF_INET: return inet_sk(sk)->mc_loop; #if IS_ENABLED(CONFIG_IPV6) case AF_INET6: return inet6_sk(sk)->mc_loop; #endif } WARN_ON(1); return true; }

Contributors

PersonTokensPropCommitsCommitProp
Hannes Frederic Sowa72100.00%1100.00%
Total72100.00%1100.00%

EXPORT_SYMBOL(sk_mc_loop); /* * This is meant for all protocols to use and covers goings on * at the socket level. Everything here is generic. */
int sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; int val; int valbool; struct linger ling; int ret = 0; /* * Options without arguments */ if (optname == SO_BINDTODEVICE) return sock_setbindtodevice(sk, optval, optlen); if (optlen < sizeof(int)) return -EINVAL; if (get_user(val, (int __user *)optval)) return -EFAULT; valbool = val ? 1 : 0; lock_sock(sk); switch (optname) { case SO_DEBUG: if (val && !capable(CAP_NET_ADMIN)) ret = -EACCES; else sock_valbool_flag(sk, SOCK_DBG, valbool); break; case SO_REUSEADDR: sk->sk_reuse = (valbool ? SK_CAN_REUSE : SK_NO_REUSE); break; case SO_REUSEPORT: sk->sk_reuseport = valbool; break; case SO_TYPE: case SO_PROTOCOL: case SO_DOMAIN: case SO_ERROR: ret = -ENOPROTOOPT; break; case SO_DONTROUTE: sock_valbool_flag(sk, SOCK_LOCALROUTE, valbool); break; case SO_BROADCAST: sock_valbool_flag(sk, SOCK_BROADCAST, valbool); break; case SO_SNDBUF: /* Don't error on this BSD doesn't and if you think * about it this is right. Otherwise apps have to * play 'guess the biggest size' games. RCVBUF/SNDBUF * are treated in BSD as hints */ val = min_t(u32, val, sysctl_wmem_max); set_sndbuf: sk->sk_userlocks |= SOCK_SNDBUF_LOCK; sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF); /* Wake up sending tasks if we upped the value. */ sk->sk_write_space(sk); break; case SO_SNDBUFFORCE: if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } goto set_sndbuf; case SO_RCVBUF: /* Don't error on this BSD doesn't and if you think * about it this is right. Otherwise apps have to * play 'guess the biggest size' games. RCVBUF/SNDBUF * are treated in BSD as hints */ val = min_t(u32, val, sysctl_rmem_max); set_rcvbuf: sk->sk_userlocks |= SOCK_RCVBUF_LOCK; /* * We double it on the way in to account for * "struct sk_buff" etc. overhead. Applications * assume that the SO_RCVBUF setting they make will * allow that much actual data to be received on that * socket. * * Applications are unaware that "struct sk_buff" and * other overheads allocate from the receive buffer * during socket buffer allocation. * * And after considering the possible alternatives, * returning the value we actually used in getsockopt * is the most desirable behavior. */ sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF); break; case SO_RCVBUFFORCE: if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } goto set_rcvbuf; case SO_KEEPALIVE: if (sk->sk_prot->keepalive) sk->sk_prot->keepalive(sk, valbool); sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); break; case SO_OOBINLINE: sock_valbool_flag(sk, SOCK_URGINLINE, valbool); break; case SO_NO_CHECK: sk->sk_no_check_tx = valbool; break; case SO_PRIORITY: if ((val >= 0 && val <= 6) || ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) sk->sk_priority = val; else ret = -EPERM; break; case SO_LINGER: if (optlen < sizeof(ling)) { ret = -EINVAL; /* 1003.1g */ break; } if (copy_from_user(&ling, optval, sizeof(ling))) { ret = -EFAULT; break; } if (!ling.l_onoff) sock_reset_flag(sk, SOCK_LINGER); else { #if (BITS_PER_LONG == 32) if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ) sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT; else #endif sk->sk_lingertime = (unsigned int)ling.l_linger * HZ; sock_set_flag(sk, SOCK_LINGER); } break; case SO_BSDCOMPAT: sock_warn_obsolete_bsdism("setsockopt"); break; case SO_PASSCRED: if (valbool) set_bit(SOCK_PASSCRED, &sock->flags); else clear_bit(SOCK_PASSCRED, &sock->flags); break; case SO_TIMESTAMP: case SO_TIMESTAMPNS: if (valbool) { if (optname == SO_TIMESTAMP) sock_reset_flag(sk, SOCK_RCVTSTAMPNS); else sock_set_flag(sk, SOCK_RCVTSTAMPNS); sock_set_flag(sk, SOCK_RCVTSTAMP); sock_enable_timestamp(sk, SOCK_TIMESTAMP); } else { sock_reset_flag(sk, SOCK_RCVTSTAMP); sock_reset_flag(sk, SOCK_RCVTSTAMPNS); } break; case SO_TIMESTAMPING: if (val & ~SOF_TIMESTAMPING_MASK) { ret = -EINVAL; break; } if (val & SOF_TIMESTAMPING_OPT_ID && !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { if (sk->sk_protocol == IPPROTO_TCP && sk->sk_type == SOCK_STREAM) { if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) { ret = -EINVAL; break; } sk->sk_tskey = tcp_sk(sk)->snd_una; } else { sk->sk_tskey = 0; } } if (val & SOF_TIMESTAMPING_OPT_STATS && !(val & SOF_TIMESTAMPING_OPT_TSONLY)) { ret = -EINVAL; break; } sk->sk_tsflags = val; if (val & SOF_TIMESTAMPING_RX_SOFTWARE) sock_enable_timestamp(sk, SOCK_TIMESTAMPING_RX_SOFTWARE); else sock_disable_timestamp(sk, (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)); break; case SO_RCVLOWAT: if (val < 0) val = INT_MAX; sk->sk_rcvlowat = val ? : 1; break; case SO_RCVTIMEO: ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen); break; case SO_SNDTIMEO: ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen); break; case SO_ATTACH_FILTER: ret = -EINVAL; if (optlen == sizeof(struct sock_fprog)) { struct sock_fprog fprog; ret = -EFAULT; if (copy_from_user(&fprog, optval, sizeof(fprog))) break; ret = sk_attach_filter(&fprog, sk); } break; case SO_ATTACH_BPF: ret = -EINVAL; if (optlen == sizeof(u32)) { u32 ufd; ret = -EFAULT; if (copy_from_user(&ufd, optval, sizeof(ufd))) break; ret = sk_attach_bpf(ufd, sk); } break; case SO_ATTACH_REUSEPORT_CBPF: ret = -EINVAL; if (optlen == sizeof(struct sock_fprog)) { struct sock_fprog fprog; ret = -EFAULT; if (copy_from_user(&fprog, optval, sizeof(fprog))) break; ret = sk_reuseport_attach_filter(&fprog, sk); } break; case SO_ATTACH_REUSEPORT_EBPF: ret = -EINVAL; if (optlen == sizeof(u32)) { u32 ufd; ret = -EFAULT; if (copy_from_user(&ufd, optval, sizeof(ufd))) break; ret = sk_reuseport_attach_bpf(ufd, sk); } break; case SO_DETACH_FILTER: ret = sk_detach_filter(sk); break; case SO_LOCK_FILTER: if (sock_flag(sk, SOCK_FILTER_LOCKED) && !valbool) ret = -EPERM; else sock_valbool_flag(sk, SOCK_FILTER_LOCKED, valbool); break; case SO_PASSSEC: if (valbool) set_bit(SOCK_PASSSEC, &sock->flags); else clear_bit(SOCK_PASSSEC, &sock->flags); break; case SO_MARK: if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) ret = -EPERM; else sk->sk_mark = val; break; case SO_RXQ_OVFL: sock_valbool_flag(sk, SOCK_RXQ_OVFL, valbool); break; case SO_WIFI_STATUS: sock_valbool_flag(sk, SOCK_WIFI_STATUS, valbool); break; case SO_PEEK_OFF: if (sock->ops->set_peek_off) ret = sock->ops->set_peek_off(sk, val); else ret = -EOPNOTSUPP; break; case SO_NOFCS: sock_valbool_flag(sk, SOCK_NOFCS, valbool); break; case SO_SELECT_ERR_QUEUE: sock_valbool_flag(sk, SOCK_SELECT_ERR_QUEUE, valbool); break; #ifdef CONFIG_NET_RX_BUSY_POLL case SO_BUSY_POLL: /* allow unprivileged users to decrease the value */ if ((val > sk->sk_ll_usec) && !capable(CAP_NET_ADMIN)) ret = -EPERM; else { if (val < 0) ret = -EINVAL; else sk->sk_ll_usec = val; } break; #endif case SO_MAX_PACING_RATE: if (val != ~0U) cmpxchg(&sk->sk_pacing_status, SK_PACING_NONE, SK_PACING_NEEDED); sk->sk_max_pacing_rate = val; sk->sk_pacing_rate = min(sk->sk_pacing_rate, sk->sk_max_pacing_rate); break; case SO_INCOMING_CPU: sk->sk_incoming_cpu = val; break; case SO_CNX_ADVICE: if (val == 1) dst_negative_advice(sk); break; case SO_ZEROCOPY: if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) ret = -ENOTSUPP; else if (sk->sk_protocol != IPPROTO_TCP) ret = -ENOTSUPP; else if (sk->sk_state != TCP_CLOSE) ret = -EBUSY; else if (val < 0 || val > 1) ret = -EINVAL; else sock_valbool_flag(sk, SOCK_ZEROCOPY, valbool); break; default: ret = -ENOPROTOOPT; break; } release_sock(sk); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)49733.58%2428.57%
Willem de Bruijn1419.53%44.76%
Eric Dumazet1318.85%910.71%
Craig Gallek1097.36%11.19%
Alexei Starovoitov533.58%11.19%
Eliezer Tamir513.45%22.38%
Patrick McHardy483.24%11.19%
Patrick Ohly442.97%11.19%
Pavel Emelyanov422.84%44.76%
Vincent Bernat312.09%11.19%
Catherine Zhang291.96%11.19%
Thomas Graf271.82%33.57%
Tom Herbert261.76%33.57%
James Morris261.76%22.38%
Tóth László Attila231.55%11.19%
Herbert Pötzl221.49%11.19%
Francis Yan211.42%11.19%
Arnaldo Carvalho de Melo191.28%22.38%
David S. Miller161.08%22.38%
Eric W. Biedermann161.08%11.19%
Johannes Berg151.01%22.38%
Ben Greear130.88%11.19%
Jacob E Keller130.88%11.19%
Linus Torvalds120.81%33.57%
Neil Horman110.74%11.19%
Soheil Hassas Yeganeh100.68%11.19%
Andi Kleen90.61%11.19%
Américo Wang70.47%22.38%
Ursula Braun70.47%11.19%
Jan Engelhardt60.41%22.38%
Sasha Levin20.14%11.19%
Rémi Denis-Courmont10.07%11.19%
Stephen Hemminger10.07%11.19%
Brian Haley10.07%11.19%
Total1480100.00%84100.00%

EXPORT_SYMBOL(sock_setsockopt);
static void cred_to_ucred(struct pid *pid, const struct cred *cred, struct ucred *ucred) { ucred->pid = pid_vnr(pid); ucred->uid = ucred->gid = -1; if (cred) { struct user_namespace *current_ns = current_user_ns(); ucred->uid = from_kuid_munged(current_ns, cred->euid); ucred->gid = from_kgid_munged(current_ns, cred->egid); } }

Contributors

PersonTokensPropCommitsCommitProp
Eric W. Biedermann8198.78%266.67%
Stephen Hemminger11.22%133.33%
Total82100.00%3100.00%


static int groups_to_user(gid_t __user *dst, const struct group_info *src) { struct user_namespace *user_ns = current_user_ns(); int i; for (i = 0; i < src->ngroups; i++) if (put_user(from_kgid_munged(user_ns, src->gid[i]), dst + i)) return -EFAULT; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David Herrmann71100.00%1100.00%
Total71100.00%1100.00%


int sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; union { int val; u64 val64; struct linger ling; struct timeval tm; } v; int lv = sizeof(int); int len; if (get_user(len, optlen)) return -EFAULT; if (len < 0) return -EINVAL; memset(&v, 0, sizeof(v)); switch (optname) { case SO_DEBUG: v.val = sock_flag(sk, SOCK_DBG); break; case SO_DONTROUTE: v.val = sock_flag(sk, SOCK_LOCALROUTE); break; case SO_BROADCAST: v.val = sock_flag(sk, SOCK_BROADCAST); break; case SO_SNDBUF: v.val = sk->sk_sndbuf; break; case SO_RCVBUF: v.val = sk->sk_rcvbuf; break; case SO_REUSEADDR: v.val = sk->sk_reuse; break; case SO_REUSEPORT: v.val = sk->sk_reuseport; break; case SO_KEEPALIVE: v.val = sock_flag(sk, SOCK_KEEPOPEN); break; case SO_TYPE: v.val = sk->sk_type; break; case SO_PROTOCOL: v.val = sk->sk_protocol; break; case SO_DOMAIN: v.val = sk->sk_family; break; case SO_ERROR: v.val = -sock_error(sk); if (v.val == 0) v.val = xchg(&sk->sk_err_soft, 0); break; case SO_OOBINLINE: v.val = sock_flag(sk, SOCK_URGINLINE); break; case SO_NO_CHECK: v.val = sk->sk_no_check_tx; break; case SO_PRIORITY: v.val = sk->sk_priority; break; case SO_LINGER: lv = sizeof(v.ling); v.ling.l_onoff = sock_flag(sk, SOCK_LINGER); v.ling.l_linger = sk->sk_lingertime / HZ; break; case SO_BSDCOMPAT: sock_warn_obsolete_bsdism("getsockopt"); break; case SO_TIMESTAMP: v.val = sock_flag(sk, SOCK_RCVTSTAMP) && !sock_flag(sk, SOCK_RCVTSTAMPNS); break; case SO_TIMESTAMPNS: v.val = sock_flag(sk, SOCK_RCVTSTAMPNS); break; case SO_TIMESTAMPING: v.val = sk->sk_tsflags; break; case SO_RCVTIMEO: lv = sizeof(struct timeval); if (sk->sk_rcvtimeo == MAX_SCHEDULE_TIMEOUT) { v.tm.tv_sec = 0; v.tm.tv_usec = 0; } else { v.tm.tv_sec = sk->sk_rcvtimeo / HZ; v.tm.tv_usec = ((sk->sk_rcvtimeo % HZ) * USEC_PER_SEC) / HZ; } break; case SO_SNDTIMEO: lv = sizeof(struct timeval); if (sk->sk_sndtimeo == MAX_SCHEDULE_TIMEOUT) { v.tm.tv_sec = 0; v.tm.tv_usec = 0; } else { v.tm.tv_sec = sk->sk_sndtimeo / HZ; v.tm.tv_usec = ((sk->sk_sndtimeo % HZ) * USEC_PER_SEC) / HZ; } break; case SO_RCVLOWAT: v.val = sk->sk_rcvlowat; break; case SO_SNDLOWAT: v.val = 1; break; case SO_PASSCRED: v.val = !!test_bit(SOCK_PASSCRED, &sock->flags); break; case SO_PEERCRED: { struct ucred peercred; if (len > sizeof(peercred)) len = sizeof(peercred); cred_to_ucred(sk->sk_peer_pid, sk->sk_peer_cred, &peercred); if (copy_to_user(optval, &peercred, len)) return -EFAULT; goto lenout; } case SO_PEERGROUPS: { int ret, n; if (!sk->sk_peer_cred) return -ENODATA; n = sk->sk_peer_cred->group_info->ngroups; if (len < n * sizeof(gid_t)) { len = n * sizeof(gid_t); return put_user(len, optlen) ? -EFAULT : -ERANGE; } len = n * sizeof(gid_t); ret = groups_to_user((gid_t __user *)optval, sk->sk_peer_cred->group_info); if (ret) return ret; goto lenout; } case SO_PEERNAME: { char address[128]; if (sock->ops->getname(sock, (struct sockaddr *)address, &lv, 2)) return -ENOTCONN; if (lv < len) return -EINVAL; if (copy_to_user(optval, address, len)) return -EFAULT; goto lenout; } /* Dubious BSD thing... Probably nobody even uses it, but * the UNIX standard wants it for whatever reason... -DaveM */ case SO_ACCEPTCONN: v.val = sk->sk_state == TCP_LISTEN; break; case SO_PASSSEC: v.val = !!test_bit(SOCK_PASSSEC, &sock->flags); break; case SO_PEERSEC: return security_socket_getpeersec_stream(sock, optval, optlen, len); case SO_MARK: v.val = sk->sk_mark; break; case SO_RXQ_OVFL: v.val = sock_flag(sk, SOCK_RXQ_OVFL); break; case SO_WIFI_STATUS: v.val = sock_flag(sk, SOCK_WIFI_STATUS); break; case SO_PEEK_OFF: if (!sock->ops->set_peek_off) return -EOPNOTSUPP; v.val = sk->sk_peek_off; break; case SO_NOFCS: v.val = sock_flag(sk, SOCK_NOFCS); break; case SO_BINDTODEVICE: return sock_getbindtodevice(sk, optval, optlen, len); case SO_GET_FILTER: len = sk_get_filter(sk, (struct sock_filter __user *)optval, len); if (len < 0) return len; goto lenout; case SO_LOCK_FILTER: v.val = sock_flag(sk, SOCK_FILTER_LOCKED); break; case SO_BPF_EXTENSIONS: v.val = bpf_tell_extensions(); break; case SO_SELECT_ERR_QUEUE: v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE); break; #ifdef CONFIG_NET_RX_BUSY_POLL case SO_BUSY_POLL: v.val = sk->sk_ll_usec; break; #endif case SO_MAX_PACING_RATE: v.val = sk->sk_max_pacing_rate; break; case SO_INCOMING_CPU: v.val = sk->sk_incoming_cpu; break; case SO_MEMINFO: { u32 meminfo[SK_MEMINFO_VARS]; if (get_user(len, optlen)) return -EFAULT; sk_get_meminfo(sk, meminfo); len = min_t(unsigned int, len, sizeof(meminfo)); if (copy_to_user(optval, &meminfo, len)) return -EFAULT; goto lenout; } #ifdef CONFIG_NET_RX_BUSY_POLL case SO_INCOMING_NAPI_ID: v.val = READ_ONCE(sk->sk_napi_id); /* aggregate non-NAPI IDs down to 0 */ if (v.val < MIN_NAPI_ID) v.val = 0; break; #endif case SO_COOKIE: lv = sizeof(u64); if (len < lv) return -EINVAL; v.val64 = sock_gen_cookie(sk); break; case SO_ZEROCOPY: v.val = sock_flag(sk, SOCK_ZEROCOPY); break; default: /* We implement the SO_SNDLOWAT etc to not be settable * (1003.1g 7). */ return -ENOPROTOOPT; } if (len > lv) len = lv; if (copy_to_user(optval, &v, len)) return -EFAULT; lenout: if (put_user(len, optlen)) return -EFAULT; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)58345.16%1826.09%
David Herrmann1048.06%11.45%
Joshua Hunt614.73%11.45%
Pavel Emelyanov614.73%34.35%
Eric Dumazet513.95%45.80%
Linus Torvalds393.02%45.80%
Sridhar Samudrala352.71%11.45%
Chenbo Feng332.56%11.45%
Arnaldo Carvalho de Melo272.09%22.90%
Jan Engelhardt241.86%22.90%
Eric W. Biedermann211.63%11.45%
Catherine Zhang191.47%22.90%
Willem de Bruijn171.32%22.90%
Eliezer Tamir161.24%22.90%
Thomas Graf151.16%34.35%
David S. Miller151.16%11.45%
Vincent Bernat151.16%11.45%
Johannes Berg151.16%11.45%
Neil Horman151.16%11.45%
Jacob E Keller151.16%11.45%
Andrew Morton141.08%11.45%
Tom Herbert131.01%22.90%
Tóth László Attila120.93%11.45%
James Morris120.93%22.90%
Michal Sekletar110.85%11.45%
Brian Haley110.85%11.45%
Eugene Teo100.77%11.45%
Patrick Ohly100.77%11.45%
Herbert Pötzl70.54%11.45%
Clément Lecigne30.23%11.45%
Mika Kukkonen20.15%11.45%
Gao Feng20.15%11.45%
Hideaki Yoshifuji/吉藤英明10.08%11.45%
Stephen Hemminger10.08%11.45%
Américo Wang10.08%11.45%
Total1291100.00%69100.00%

/* * Initialize an sk_lock. * * (We also register the sk_lock with the lock validator.) */
static inline void sock_lock_init(struct sock *sk) { if (sk->sk_kern_sock) sock_lock_init_class_and_name( sk, af_family_kern_slock_key_strings[sk->sk_family], af_family_kern_slock_keys + sk->sk_family, af_family_kern_key_strings[sk->sk_family], af_family_kern_keys + sk->sk_family); else sock_lock_init_class_and_name( sk, af_family_slock_key_strings[sk->sk_family], af_family_slock_keys + sk->sk_family, af_family_key_strings[sk->sk_family], af_family_keys + sk->sk_family); }

Contributors

PersonTokensPropCommitsCommitProp
David Howells3846.91%125.00%
Ingo Molnar3745.68%125.00%
Peter Zijlstra56.17%125.00%
Dave Jones11.23%125.00%
Total81100.00%4100.00%

/* * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, * even temporarly, because of RCU lookups. sk_node should also be left as is. * We must not copy fields between sk_dontcopy_begin and sk_dontcopy_end */
static void sock_copy(struct sock *nsk, const struct sock *osk) { #ifdef CONFIG_SECURITY_NETWORK void *sptr = nsk->sk_security; #endif memcpy(nsk, osk, offsetof(struct sock, sk_dontcopy_begin)); memcpy(&nsk->sk_dontcopy_end, &osk->sk_dontcopy_end, osk->sk_prot->obj_size - offsetof(struct sock, sk_dontcopy_end)); #ifdef CONFIG_SECURITY_NETWORK nsk->sk_security = sptr; security_sk_clone(osk, nsk); #endif }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov6167.78%125.00%
Eric Dumazet2831.11%250.00%
Krishna Kumar11.11%125.00%
Total90100.00%4100.00%


static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, int family) { struct sock *sk; struct kmem_cache *slab; slab = prot->slab; if (slab != NULL) { sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO); if (!sk) return sk; if (priority & __GFP_ZERO) sk_prot_clear_nulls(sk, prot->obj_size); } else sk = kmalloc(prot->obj_size, priority); if (sk != NULL) { kmemcheck_annotate_bitfield(sk, flags); if (security_sk_alloc(sk, family, priority)) goto out_free; if (!try_module_get(prot->owner)) goto out_free_sec; sk_tx_queue_clear(sk); } return sk; out_free_sec: security_sk_free(sk); out_free: if (slab != NULL) kmem_cache_free(slab, sk); else kfree(sk); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov8147.37%215.38%
Eric Dumazet2715.79%17.69%
Arnaldo Carvalho de Melo2514.62%215.38%
Linus Torvalds (pre-git)158.77%215.38%
David S. Miller74.09%17.69%
Vegard Nossum74.09%17.69%
Krishna Kumar52.92%17.69%
Christoph Lameter21.17%17.69%
Octavian Purdila10.58%17.69%
Eric W. Biedermann10.58%17.69%
Total171100.00%13100.00%


static void sk_prot_free(struct proto *prot, struct sock *sk) { struct kmem_cache *slab; struct module *owner; owner = prot->owner; slab = prot->slab; cgroup_sk_free(&sk->sk_cgrp_data); mem_cgroup_sk_free(sk); security_sk_free(sk); if (slab != NULL) kmem_cache_free(slab, sk); else kfree(sk); module_put(owner); }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov6783.75%250.00%
Tejun Heo810.00%125.00%
Johannes Weiner56.25%125.00%
Total80100.00%4100.00%

/** * sk_alloc - All socket objects are allocated here * @net: the applicable net namespace * @family: protocol family * @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc) * @prot: struct proto associated with this new sock instance * @kern: is this to be a kernel socket? */
struct sock *sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot, int kern) { struct sock *sk; sk = sk_prot_alloc(prot, priority | __GFP_ZERO, family); if (sk) { sk->sk_family = family; /* * See comment in struct sock definition to understand * why we need sk_prot_creator -acme */ sk->sk_prot = sk->sk_prot_creator = prot; sk->sk_kern_sock = kern; sock_lock_init(sk); sk->sk_net_refcnt = kern ? 0 : 1; if (likely(sk->sk_net_refcnt)) get_net(net); sock_net_set(sk, net); refcount_set(&sk->sk_wmem_alloc, 1); mem_cgroup_sk_alloc(sk); cgroup_sk_alloc(&sk->sk_cgrp_data); sock_update_classid(&sk->sk_cgrp_data); sock_update_netprioidx(&sk->sk_cgrp_data); } return sk; }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov4127.15%313.04%
Eric W. Biedermann3221.19%313.04%
Linus Torvalds (pre-git)159.93%313.04%
Johannes Weiner138.61%28.70%
Arnaldo Carvalho de Melo117.28%313.04%
Jarek Poplawski95.96%14.35%
David Howells63.97%14.35%
Tejun Heo63.97%14.35%
Neil Horman53.31%14.35%
Herbert Xu53.31%14.35%
Frank Filz31.99%14.35%
Hideaki Yoshifuji / 吉藤英明21.32%14.35%
David S. Miller21.32%14.35%
Elena Reshetova10.66%14.35%
Total151100.00%23100.00%

EXPORT_SYMBOL(sk_alloc); /* Sockets having SOCK_RCU_FREE will call this function after one RCU * grace period. This is the case for UDP sockets and TCP listeners. */
static void __sk_destruct(struct rcu_head *head) { struct sock *sk = container_of(head, struct sock, sk_rcu); struct sk_filter *filter; if (sk->sk_destruct) sk->sk_destruct(sk); filter = rcu_dereference_check(sk->sk_filter, refcount_read(&sk->sk_wmem_alloc) == 0); if (filter) { sk_filter_uncharge(sk, filter); RCU_INIT_POINTER(sk->sk_filter, NULL); } if (rcu_access_pointer(sk->sk_reuseport_cb)) reuseport_detach_sock(sk); sock_disable_timestamp(sk, SK_FLAGS_TIMESTAMP); if (atomic_read(&sk->sk_omem_alloc)) pr_debug("%s: optmem leakage (%d bytes) detected\n", __func__, atomic_read(&sk->sk_omem_alloc)); if (sk->sk_frag.page) { put_page(sk->sk_frag.page); sk->sk_frag.page = NULL; } if (sk->sk_peer_cred) put_cred(sk->sk_peer_cred); put_pid(sk->sk_peer_pid); if (likely(sk->sk_net_refcnt)) put_net(sock_net(sk)); sk_prot_free(sk->sk_prot_creator, sk); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)6833.33%622.22%
Eric Dumazet4723.04%311.11%
Eric W. Biedermann3416.67%311.11%
Craig Gallek146.86%13.70%
Paul E. McKenney104.90%13.70%
Arnaldo Carvalho de Melo83.92%27.41%
Dmitry Mishin52.45%13.70%
Andi Kleen52.45%13.70%
Hideaki Yoshifuji / 吉藤英明31.47%13.70%
Joe Perches20.98%13.70%
David S. Miller20.98%13.70%
Pavel Emelyanov20.98%27.41%
Elena Reshetova10.49%13.70%
Stephen Hemminger10.49%13.70%
Harvey Harrison10.49%13.70%
Patrick Ohly10.49%13.70%
Total204100.00%27100.00%


void sk_destruct(struct sock *sk) { if (sock_flag(sk, SOCK_RCU_FREE)) call_rcu(&sk->sk_rcu, __sk_destruct); else __sk_destruct(&sk->sk_rcu); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet38100.00%1100.00%
Total38100.00%1100.00%


static void __sk_free(struct sock *sk) { if (unlikely(sock_diag_has_destroy_listeners(sk) && sk->sk_net_refcnt)) sock_diag_broadcast_destroy(sk); else sk_destruct(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Craig Gallek36100.00%2100.00%
Total36100.00%2100.00%


void sk_free(struct sock *sk) { /* * We subtract one from sk_wmem_alloc and can know if * some packets are still in some tx queue. * If not null, sock_wfree() will call __sk_free(sk) later */ if (refcount_dec_and_test(&sk->sk_wmem_alloc)) __sk_free(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet2492.31%133.33%
Elena Reshetova13.85%133.33%
Lucas De Marchi13.85%133.33%
Total26100.00%3100.00%

EXPORT_SYMBOL(sk_free);
static void sk_init_common(struct sock *sk) { skb_queue_head_init(&sk->sk_receive_queue); skb_queue_head_init(&sk->sk_write_queue); skb_queue_head_init(&sk->sk_error_queue); rwlock_init(&sk->sk_callback_lock); lockdep_set_class_and_name(&sk->sk_receive_queue.lock, af_rlock_keys + sk->sk_family, af_family_rlock_key_strings[sk->sk_family]); lockdep_set_class_and_name(&sk->sk_write_queue.lock, af_wlock_keys + sk->sk_family, af_family_wlock_key_strings[sk->sk_family]); lockdep_set_class_and_name(&sk->sk_error_queue.lock, af_elock_keys + sk->sk_family, af_family_elock_key_strings[sk->sk_family]); lockdep_set_class_and_name(&sk->sk_callback_lock, af_callback_keys + sk->sk_family, af_family_clock_key_strings[sk->sk_family]); }

Contributors

PersonTokensPropCommitsCommitProp
Paolo Abeni133100.00%1100.00%
Total133100.00%1100.00%

/** * sk_clone_lock - clone a socket, and lock its clone * @sk: the socket to clone * @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc) * * Caller must unlock socket even in error path (bh_unlock_sock(newsk)) */
struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) { struct sock *newsk; bool is_charged = true; newsk = sk_prot_alloc(sk->sk_prot, priority, sk->sk_family); if (newsk != NULL) { struct sk_filter *filter; sock_copy(newsk, sk); newsk->sk_prot_creator = sk->sk_prot; /* SANITY */ if (likely(newsk->sk_net_refcnt)) get_net(sock_net(newsk)); sk_node_init(&newsk->sk_node); sock_lock_init(newsk); bh_lock_sock(newsk); newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; newsk->sk_backlog.len = 0; atomic_set(&newsk->sk_rmem_alloc, 0); /* * sk_wmem_alloc set to one (see sk_free() and sock_wfree()) */ refcount_set(&newsk->sk_wmem_alloc, 1); atomic_set(&newsk->sk_omem_alloc, 0); sk_init_common(newsk); newsk->sk_dst_cache = NULL; newsk->sk_dst_pending_confirm = 0; newsk->sk_wmem_queued = 0; newsk->sk_forward_alloc = 0; /* sk->sk_memcg will be populated at accept() time */ newsk->sk_memcg = NULL; atomic_set(&newsk->sk_drops, 0); newsk->sk_send_head = NULL; newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; atomic_set(&newsk->sk_zckey, 0); sock_reset_flag(newsk, SOCK_DONE); cgroup_sk_alloc(&newsk->sk_cgrp_data); rcu_read_lock(); filter = rcu_dereference(sk->sk_filter); if (filter != NULL) /* though it's an empty new sock, the charging may fail * if sysctl_optmem_max was changed between creation of * original socket and cloning */ is_charged = sk_filter_charge(newsk, filter); RCU_INIT_POINTER(newsk->sk_filter, filter); rcu_read_unlock(); if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) { /* We need to make sure that we don't uncharge the new * socket if we couldn't charge it in the first place * as otherwise we uncharge the parent's filter. */ if (!is_charged) RCU_INIT_POINTER(newsk->sk_filter, NULL); sk_free_unlock_clone(newsk); newsk = NULL; goto out; } RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL); newsk->sk_err = 0; newsk->sk_err_soft = 0; newsk->sk_priority = 0; newsk->sk_incoming_cpu = raw_smp_processor_id(); atomic64_set(&newsk->sk_cookie, 0); /* * Before updating sk_refcnt, we must commit prior changes to memory * (Documentation/RCU/rculist_nulls.txt for details) */ smp_wmb(); refcount_set(&newsk->sk_refcnt, 2); /* * Increment the counter in the same struct proto as the master * sock (sk_refcnt_debug_inc uses newsk->sk_prot->socks, that * is the same as sk->sk_prot->socks, as this field was copied * with memcpy). * * This _changes_ the previous behaviour, where * tcp_create_openreq_child always was incrementing the * equivalent to tcp_prot->socks (inet_sock_nr), so this have * to be taken into account in all callers. -acme */ sk_refcnt_debug_inc(newsk); sk_set_socket(newsk, NULL); newsk->sk_wq = NULL; if (newsk->sk_prot->sockets_allocated) sk_sockets_allocated_inc(newsk); if (sock_needs_netstamp(sk) && newsk->sk_flags & SK_FLAGS_TIMESTAMP) net_enable_timestamp(); } out: return newsk; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo22851.58%25.00%
Eric Dumazet9521.49%1537.50%
Daniel Borkmann153.39%12.50%
Pavel Emelyanov122.71%25.00%
Alexei Starovoitov112.49%12.50%
Willem de Bruijn102.26%12.50%
Craig Gallek92.04%12.50%
Sowmini Varadhan92.04%12.50%
Yi Zhu81.81%12.50%
Christoph Paasch81.81%12.50%
Octavian Purdila71.58%12.50%
Julian Anastasov61.36%12.50%
Hannes Frederic Sowa51.13%12.50%
David S. Miller40.90%12.50%
Hideaki Yoshifuji / 吉藤英明30.68%12.50%
Ingo Molnar30.68%12.50%
Johannes Weiner20.45%12.50%
Elena Reshetova20.45%25.00%
Venkat Yekkirala10.23%12.50%
Peter Zijlstra10.23%12.50%
Glauber de Oliveira Costa10.23%12.50%
Paolo Abeni10.23%12.50%
Al Viro10.23%12.50%
Total442100.00%40100.00%

EXPORT_SYMBOL_GPL(sk_clone_lock);
void sk_free_unlock_clone(struct sock *sk) { /* It is still raw copy of parent, so invalidate * destructor and make plain sk_free() */ sk->sk_destruct = NULL; bh_unlock_sock(sk); sk_free(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo27100.00%1100.00%
Total27100.00%1100.00%

EXPORT_SYMBOL_GPL(sk_free_unlock_clone);
void sk_setup_caps(struct sock *sk, struct dst_entry *dst) { u32 max_segs = 1; sk_dst_set(sk, dst); sk->sk_route_caps = dst->dev->features; if (sk->sk_route_caps & NETIF_F_GSO) sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE; sk->sk_route_caps &= ~sk->sk_route_nocaps; if (sk_can_gso(sk)) { if (dst->header_len && !xfrm_dst_offload_ok(dst)) { sk->sk_route_caps &= ~NETIF_F_GSO_MASK; } else { sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; sk->sk_gso_max_size = dst->dev->gso_max_size; max_segs = max_t(u32, dst->dev->gso_max_segs, 1); } } sk->sk_gso_max_segs = max_segs; }

Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen7556.82%112.50%
Eric Dumazet2921.97%337.50%
Peter P. Waskiewicz Jr1410.61%112.50%
Ben Hutchings75.30%112.50%
Steffen Klassert64.55%112.50%
Herbert Xu10.76%112.50%
Total132100.00%8100.00%

EXPORT_SYMBOL_GPL(sk_setup_caps); /* * Simple resource managers for sockets. */ /* * Write buffer destructor automatically called from kfree_skb. */
void sock_wfree(struct sk_buff *skb) { struct sock *sk = skb->sk; unsigned int len = skb->truesize; if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) { /* * Keep a reference on sk_wmem_alloc, this will be released * after sk_write_space() call */ WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc)); sk->sk_write_space(sk); len = 1; } /* * if sk_wmem_alloc reaches 0, we must finish what sk_free() * could not do because of in-flight packets */ if (refcount_sub_and_test(len, &sk->sk_wmem_alloc)) __sk_free(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet3642.86%225.00%
Linus Torvalds (pre-git)3238.10%225.00%
Elena Reshetova55.95%112.50%
Linus Torvalds55.95%112.50%
Thomas Graf55.95%112.50%
Arnaldo Carvalho de Melo11.19%112.50%
Total84100.00%8100.00%

EXPORT_SYMBOL(sock_wfree); /* This variant of sock_wfree() is used by TCP, * since it sets SOCK_USE_WRITE_QUEUE. */
void __sock_wfree(struct sk_buff *skb) { struct sock *sk = skb->sk; if (refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc)) __sk_free(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet3797.37%150.00%
Elena Reshetova12.63%150.00%
Total38100.00%2100.00%


void skb_set_owner_w(struct sk_buff *skb, struct sock *sk) { skb_orphan(skb); skb->sk = sk; #ifdef CONFIG_INET if (unlikely(!sk_fullsock(sk))) { skb->destructor = sock_edemux; sock_hold(sk); return; } #endif skb->destructor = sock_wfree; skb_set_hash_from_sk(skb, sk); /* * We used to take a refcount on sk, but following operation * is enough to guarantee sk_free() wont free this sock until * all in-flight packets are completed */ refcount_add(skb->truesize, &sk->sk_wmem_alloc); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet8198.78%150.00%
Elena Reshetova11.22%150.00%
Total82100.00%2100.00%

EXPORT_SYMBOL(skb_set_owner_w); /* This helper is used by netem, as it can hold packets in its * delay queue. We want to allow the owner socket to send more * packets, as if they were already TX completed by a typical driver. * But we also want to keep skb->sk set because some packet schedulers * rely on it (sch_fq for example). */
void skb_orphan_partial(struct sk_buff *skb) { if (skb_is_tcp_pure_ack(skb)) return; if (skb->destructor == sock_wfree #ifdef CONFIG_INET || skb->destructor == tcp_wfree #endif ) { struct sock *sk = skb->sk; if (refcount_inc_not_zero(&sk->sk_refcnt)) { WARN_ON(refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc)); skb->destructor = sock_efree; } } else { skb_orphan(skb); } }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet8494.38%360.00%
Elena Reshetova55.62%240.00%
Total89100.00%5100.00%

EXPORT_SYMBOL(skb_orphan_partial); /* * Read buffer destructor automatically called from kfree_skb. */
void sock_rfree(struct sk_buff *skb) { struct sock *sk = skb->sk; unsigned int len = skb->truesize; atomic_sub(len, &sk->sk_rmem_alloc); sk_mem_uncharge(sk, len); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2863.64%125.00%
Eric Dumazet920.45%125.00%
Hideo Aoki613.64%125.00%
Arnaldo Carvalho de Melo12.27%125.00%
Total44100.00%4100.00%

EXPORT_SYMBOL(sock_rfree); /* * Buffer destructor for skbs that are not used directly in read or write * path, e.g. for error handler skbs. Automatically called from kfree_skb. */
void sock_efree(struct sk_buff *skb) { sock_put(skb->sk); }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Duyck17100.00%1100.00%
Total17100.00%1100.00%

EXPORT_SYMBOL(sock_efree);
kuid_t sock_i_uid(struct sock *sk) { kuid_t uid; read_lock_bh(&sk->sk_callback_lock); uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : GLOBAL_ROOT_UID; read_unlock_bh(&sk->sk_callback_lock); return uid; }

Contributors

PersonTokensPropCommitsCommitProp
Stephen Hemminger4489.80%133.33%
Eric W. Biedermann36.12%133.33%
Eric Dumazet24.08%133.33%
Total49100.00%3100.00%

EXPORT_SYMBOL(sock_i_uid);
unsigned long sock_i_ino(struct sock *sk) { unsigned long ino; read_lock_bh(&sk->sk_callback_lock); ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0; read_unlock_bh(&sk->sk_callback_lock); return ino; }

Contributors

PersonTokensPropCommitsCommitProp
Stephen Hemminger4996.08%150.00%
Eric Dumazet23.92%150.00%
Total51100.00%2100.00%

EXPORT_SYMBOL(sock_i_ino); /* * Allocate a skb from the socket's send buffer. */
struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, gfp_t priority) { if (force || refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { struct sk_buff *skb = alloc_skb(size, priority); if (skb) { skb_set_owner_w(skb, sk); return skb; } } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)6794.37%1178.57%
Arnaldo Carvalho de Melo22.82%17.14%
Elena Reshetova11.41%17.14%
Al Viro11.41%17.14%
Total71100.00%14100.00%

EXPORT_SYMBOL(sock_wmalloc);
static void sock_ofree(struct sk_buff *skb) { struct sock *sk = skb->sk; atomic_sub(skb->truesize, &sk->sk_omem_alloc); }

Contributors

PersonTokensPropCommitsCommitProp
Willem de Bruijn32100.00%1100.00%
Total32100.00%1100.00%


struct sk_buff *sock_omalloc(struct sock *sk, unsigned long size, gfp_t priority) { struct sk_buff *skb; /* small safe race: SKB_TRUESIZE may differ from final skb->truesize */ if (atomic_read(&sk->sk_omem_alloc) + SKB_TRUESIZE(size) > sysctl_optmem_max) return NULL; skb = alloc_skb(size, priority); if (!skb) return NULL; atomic_add(skb->truesize, &sk->sk_omem_alloc); skb->sk = sk; skb->destructor = sock_ofree; return skb; }

Contributors

PersonTokensPropCommitsCommitProp
Willem de Bruijn89100.00%1100.00%
Total89100.00%1100.00%

/* * Allocate a memory block from the socket's option memory buffer. */
void *sock_kmalloc(struct sock *sk, int size, gfp_t priority) { if ((unsigned int)size <= sysctl_optmem_max && atomic_read(&sk->sk_omem_alloc) + size < sysctl_optmem_max) { void *mem; /* First do the add, to avoid the race if kmalloc * might sleep. */ atomic_add(size, &sk->sk_omem_alloc); mem = kmalloc(size, priority); if (mem) return mem; atomic_sub(size, &sk->sk_omem_alloc); } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7992.94%450.00%
Arnaldo Carvalho de Melo33.53%112.50%
Al Viro11.18%112.50%
Hideaki Yoshifuji / 吉藤英明11.18%112.50%
Eric Dumazet11.18%112.50%
Total85100.00%8100.00%

EXPORT_SYMBOL(sock_kmalloc); /* Free an option memory block. Note, we actually want the inline * here as this allows gcc to detect the nullify and fold away the * condition entirely. */
static inline void __sock_kfree_s(struct sock *sk, void *mem, int size, const bool nullify) { if (WARN_ON_ONCE(!mem)) return; if (nullify) kzfree(mem); else kfree(mem); atomic_sub(size, &sk->sk_omem_alloc); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3052.63%240.00%
Daniel Borkmann1729.82%120.00%
David S. Miller915.79%120.00%
Arnaldo Carvalho de Melo11.75%120.00%
Total57100.00%5100.00%


void sock_kfree_s(struct sock *sk, void *mem, int size) { __sock_kfree_s(sk, mem, size, false); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann28100.00%1100.00%
Total28100.00%1100.00%

EXPORT_SYMBOL(sock_kfree_s);
void sock_kzfree_s(struct sock *sk, void *mem, int size) { __sock_kfree_s(sk, mem, size, true); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann28100.00%1100.00%
Total28100.00%1100.00%

EXPORT_SYMBOL(sock_kzfree_s); /* It is almost wait_for_tcp_memory minus release_sock/lock_sock. I think, these locks should be removed for datagram sockets. */
static long sock_wait_for_wmem(struct sock *sk, long timeo) { DEFINE_WAIT(wait); sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); for (;;) { if (!timeo) break; if (signal_pending(current)) break; set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); if (refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) break; if (sk->sk_shutdown & SEND_SHUTDOWN) break; if (sk->sk_err) break; timeo = schedule_timeout(timeo); } finish_wait(sk_sleep(sk), &wait); return timeo; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)9576.61%545.45%
Eric Dumazet86.45%218.18%
Arnaldo Carvalho de Melo75.65%19.09%
Andrew Morton75.65%19.09%
Linus Torvalds64.84%19.09%
Elena Reshetova10.81%19.09%
Total124100.00%11100.00%

/* * Generic send/receive buffer handlers */
struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, unsigned long data_len, int noblock, int *errcode, int max_page_order) { struct sk_buff *skb; long timeo; int err; timeo = sock_sndtimeo(sk, noblock); for (;;) { err = sock_error(sk); if (err != 0) goto failure; err = -EPIPE; if (sk->sk_shutdown & SEND_SHUTDOWN) goto failure; if (sk_wmem_alloc_get(sk) < sk->sk_sndbuf) break; sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); err = -EAGAIN; if (!timeo) goto failure; if (signal_pending(current)) goto interrupted; timeo = sock_wait_for_wmem(sk, timeo); } skb = alloc_skb_with_frags(header_len, data_len, max_page_order, errcode, sk->sk_allocation); if (skb) skb_set_owner_w(skb, sk); return skb; interrupted: err = sock_intr_errno(timeo); failure: *errcode = err; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)11657.43%956.25%
Eric Dumazet7135.15%425.00%
Linus Torvalds125.94%16.25%
Arnaldo Carvalho de Melo20.99%16.25%
David S. Miller10.50%16.25%
Total202100.00%16100.00%

EXPORT_SYMBOL(sock_alloc_send_pskb);
struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, int noblock, int *errcode) { return sock_alloc_send_pskb(sk, size, 0, noblock, errcode, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds3794.87%150.00%
Eric Dumazet25.13%150.00%
Total39100.00%2100.00%

EXPORT_SYMBOL(sock_alloc_send_skb);
int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, struct sockcm_cookie *sockc) { u32 tsflags; switch (cmsg->cmsg_type) { case SO_MARK: if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) return -EPERM; if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32))) return -EINVAL; sockc->mark = *(u32 *)CMSG_DATA(cmsg); break; case SO_TIMESTAMPING: if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32))) return -EINVAL; tsflags = *(u32 *)CMSG_DATA(cmsg); if (tsflags & ~SOF_TIMESTAMPING_TX_RECORD_MASK) return -EINVAL; sockc->tsflags &= ~SOF_TIMESTAMPING_TX_RECORD_MASK; sockc->tsflags |= tsflags; break; /* SCM_RIGHTS and SCM_CREDENTIALS are semantically in SOL_UNIX. */ case SCM_RIGHTS: case SCM_CREDENTIALS: break; default: return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Edward Hyunkoo Jee8652.12%125.00%
Soheil Hassas Yeganeh6941.82%250.00%
Willem de Bruijn106.06%125.00%
Total165100.00%4100.00%

EXPORT_SYMBOL(__sock_cmsg_send);
int sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct sockcm_cookie *sockc) { struct cmsghdr *cmsg; int ret; for_each_cmsghdr(cmsg, msg) { if (!CMSG_OK(msg, cmsg)) return -EINVAL; if (cmsg->cmsg_level != SOL_SOCKET) continue; ret = __sock_cmsg_send(sk, msg, cmsg, sockc); if (ret) return ret; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Willem de Bruijn7793.90%150.00%
Edward Hyunkoo Jee56.10%150.00%
Total82100.00%2100.00%

EXPORT_SYMBOL(sock_cmsg_send);
static void sk_enter_memory_pressure(struct sock *sk) { if (!sk->sk_prot->enter_memory_pressure) return; sk->sk_prot->enter_memory_pressure(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet30100.00%1100.00%
Total30100.00%1100.00%


static void sk_leave_memory_pressure(struct sock *sk) { if (sk->sk_prot->leave_memory_pressure) { sk->sk_prot->leave_memory_pressure(sk); } else { unsigned long *memory_pressure = sk->sk_prot->memory_pressure; if (memory_pressure && *memory_pressure) *memory_pressure = 0; } }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet56100.00%1100.00%
Total56100.00%1100.00%

/* On 32bit arches, an skb frag is limited to 2^15 */ #define SKB_FRAG_PAGE_ORDER get_order(32768) /** * skb_page_frag_refill - check that a page_frag contains enough room * @sz: minimum size of the fragment we want to get * @pfrag: pointer to page_frag * @gfp: priority for memory allocation * * Note: While this allocator tries to use high order pages, there is * no guarantee that allocations succeed. Therefore, @sz MUST be * less or equal than PAGE_SIZE. */
bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t gfp) { if (pfrag->page) { if (page_ref_count(pfrag->page) == 1) { pfrag->offset = 0; return true; } if (pfrag->offset + sz <= pfrag->size) return true; put_page(pfrag->page); } pfrag->offset = 0; if (SKB_FRAG_PAGE_ORDER) { /* Avoid direct reclaim but allow kswapd to wake */ pfrag->page = alloc_pages((gfp & ~__GFP_DIRECT_RECLAIM) | __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY, SKB_FRAG_PAGE_ORDER); if (likely(pfrag->page)) { pfrag->size = PAGE_SIZE << SKB_FRAG_PAGE_ORDER; return true; } } pfrag->page = alloc_page(gfp); if (likely(pfrag->page)) { pfrag->size = PAGE_SIZE; return true; } return false; }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet15195.57%457.14%
Shaohua Li42.53%114.29%
Mel Gorman21.27%114.29%
JoonSoo Kim10.63%114.29%
Total158100.00%7100.00%

EXPORT_SYMBOL(skb_page_frag_refill);
bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag) { if (likely(skb_page_frag_refill(32U, pfrag, sk->sk_allocation))) return true; sk_enter_memory_pressure(sk); sk_stream_moderate_sndbuf(sk); return false; }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet47100.00%2100.00%
Total47100.00%2100.00%

EXPORT_SYMBOL(sk_page_frag_refill);
static void __lock_sock(struct sock *sk) __releases(&sk->sk_lock.slock

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)866.67%360.00%
Namhyung Kim325.00%120.00%
Arjan van de Ven18.33%120.00%
Total12100.00%5100.00%

) __acquires(&sk->sk_lock.slock) { DEFINE_WAIT(wait); for (;;) { prepare_to_wait_exclusive(&sk->sk_lock.wq, &wait, TASK_UNINTERRUPTIBLE); spin_unlock_bh(&sk->sk_lock.slock); schedule(); spin_lock_bh(&sk->sk_lock.slock); if (!sock_owned_by_user(sk)) break; } finish_wait(&sk->sk_lock.wq, &wait); }
static void __release_sock(struct sock *sk) __releases(&sk->sk_lock.slock

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)866.67%250.00%
Namhyung Kim325.00%125.00%
Arjan van de Ven18.33%125.00%
Total12100.00%4100.00%

) __acquires(&sk->sk_lock.slock) { struct sk_buff *skb, *next; while ((skb = sk->sk_backlog.head) != NULL) { sk->sk_backlog.head = sk->sk_backlog.tail = NULL; spin_unlock_bh(&sk->sk_lock.slock); do { next = skb->next; prefetch(next); WARN_ON_ONCE(skb_dst_is_noref(skb)); skb->next = NULL; sk_backlog_rcv(sk, skb); cond_resched(); skb = next; } while (skb != NULL); spin_lock_bh(&sk->sk_lock.slock); } /* * Doing the zeroing here guarantee we can not loop forever * while a wild producer attempts to flood us. */ sk->sk_backlog.len = 0; }
void __sk_flush_backlog(struct sock *sk) { spin_lock_bh(&sk->sk_lock.slock); __release_sock(sk); spin_unlock_bh(&sk->sk_lock.slock); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet35100.00%1100.00%
Total35100.00%1100.00%

/** * sk_wait_data - wait for data to arrive at sk_receive_queue * @sk: sock to wait on * @timeo: for how long * @skb: last skb seen on sk_receive_queue * * Now socket state including sk->sk_err is changed only under lock, * hence we may omit checks after joining wait queue. * We check receive queue before schedule() only as optimization; * it is very likely that release_sock() added new data. */
int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb) { DEFINE_WAIT_FUNC(wait, woken_wake_function); int rc; add_wait_queue(sk_sleep(sk), &wait); sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb, &wait); sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); remove_wait_queue(sk_sleep(sk), &wait); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo6167.03%120.00%
Américo Wang1112.09%120.00%
Eric Dumazet1010.99%240.00%
Sabrina Dubroca99.89%120.00%
Total91100.00%5100.00%

EXPORT_SYMBOL(sk_wait_data); /** * __sk_mem_raise_allocated - increase memory_allocated * @sk: socket * @size: memory size to allocate * @amt: pages to allocate * @kind: allocation type * * Similar to __sk_mem_schedule(), but does not update sk_forward_alloc */
int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind) { struct proto *prot = sk->sk_prot; long allocated = sk_memory_allocated_add(sk, amt); if (mem_cgroup_sockets_enabled && sk->sk_memcg && !mem_cgroup_charge_skmem(sk->sk_memcg, amt)) goto suppress_allocation; /* Under limit. */ if (allocated <= sk_prot_mem_limits(sk, 0)) { sk_leave_memory_pressure(sk); return 1; } /* Under pressure. */ if (allocated > sk_prot_mem_limits(sk, 1)) sk_enter_memory_pressure(sk); /* Over hard limit. */ if (allocated > sk_prot_mem_limits(sk, 2)) goto suppress_allocation; /* guarantee minimum buffer size under pressure */ if (kind == SK_MEM_RECV) { if (atomic_read(&sk->sk_rmem_alloc) < prot->sysctl_rmem[0]) return 1; } else { /* SK_MEM_SEND */ if (sk->sk_type == SOCK_STREAM) { if (sk->sk_wmem_queued < prot->sysctl_wmem[0]) return 1; } else if (refcount_read(&sk->sk_wmem_alloc) < prot->sysctl_wmem[0]) return 1; } if (sk_has_memory_pressure(sk)) { int alloc; if (!sk_under_memory_pressure(sk)) return 1; alloc = sk_sockets_allocated_read_positive(sk); if (sk_prot_mem_limits(sk, 2) > alloc * sk_mem_pages(sk->sk_wmem_queued + atomic_read(&sk->sk_rmem_alloc) + sk->sk_forward_alloc)) return 1; } suppress_allocation: if (kind == SK_MEM_SEND && sk->sk_type == SOCK_STREAM) { sk_stream_moderate_sndbuf(sk); /* Fail only if socket is _under_ its sndbuf. * In this case we cannot block, so that we have to fail. */ if (sk->sk_wmem_queued + size >= sk->sk_sndbuf) return 1; } trace_sock_exceed_buf_limit(sk, prot, allocated); sk_memory_allocated_sub(sk, amt); if (mem_cgroup_sockets_enabled && sk->sk_memcg) mem_cgroup_uncharge_skmem(sk->sk_memcg, amt); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Hideo Aoki21264.44%19.09%
Glauber de Oliveira Costa4212.77%218.18%
Johannes Weiner4012.16%218.18%
Eric Dumazet164.86%218.18%
Satoru Moriya92.74%19.09%
Paolo Abeni61.82%19.09%
Pavel Emelyanov30.91%19.09%
Elena Reshetova10.30%19.09%
Total329100.00%11100.00%

EXPORT_SYMBOL(__sk_mem_raise_allocated); /** * __sk_mem_schedule - increase sk_forward_alloc and memory_allocated * @sk: socket * @size: memory size to allocate * @kind: allocation type * * If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means * rmem allocation. This function assumes that protocols which have * memory_pressure use sk_wmem_queued as write buffer accounting. */
int __sk_mem_schedule(struct sock *sk, int size, int kind) { int ret, amt = sk_mem_pages(size); sk->sk_forward_alloc += amt << SK_MEM_QUANTUM_SHIFT; ret = __sk_mem_raise_allocated(sk, size, amt, kind); if (!ret) sk->sk_forward_alloc -= amt << SK_MEM_QUANTUM_SHIFT; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Paolo Abeni4063.49%125.00%
Hideo Aoki1523.81%125.00%
Eric Dumazet711.11%125.00%
Glauber de Oliveira Costa11.59%125.00%
Total63100.00%4100.00%

EXPORT_SYMBOL(__sk_mem_schedule); /** * __sk_mem_reduce_allocated - reclaim memory_allocated * @sk: socket * @amount: number of quanta * * Similar to __sk_mem_reclaim(), but does not update sk_forward_alloc */
void __sk_mem_reduce_allocated(struct sock *sk, int amount) { sk_memory_allocated_sub(sk, amount); if (mem_cgroup_sockets_enabled && sk->sk_memcg) mem_cgroup_uncharge_skmem(sk->sk_memcg, amount); if (sk_under_memory_pressure(sk) && (sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0))) sk_leave_memory_pressure(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Paolo Abeni1930.16%120.00%
Johannes Weiner1726.98%240.00%
Glauber de Oliveira Costa1523.81%120.00%
Hideo Aoki1219.05%120.00%
Total63100.00%5100.00%

EXPORT_SYMBOL(__sk_mem_reduce_allocated); /** * __sk_mem_reclaim - reclaim sk_forward_alloc and memory_allocated * @sk: socket * @amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple) */
void __sk_mem_reclaim(struct sock *sk, int amount) { amount >>= SK_MEM_QUANTUM_SHIFT; sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT; __sk_mem_reduce_allocated(sk, amount); }

Contributors

PersonTokensPropCommitsCommitProp
Paolo Abeni32100.00%1100.00%
Total32100.00%1100.00%

EXPORT_SYMBOL(__sk_mem_reclaim);
int sk_set_peek_off(struct sock *sk, int val) { sk->sk_peek_off = val; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
samanthakumar22100.00%1100.00%
Total22100.00%1100.00%

EXPORT_SYMBOL_GPL(sk_set_peek_off); /* * Set of default routines for initialising struct proto_ops when * the protocol does not support a particular function. In certain * cases where it makes no sense for a protocol to have a "do nothing" * function, some default processing is provided. */
int sock_no_bind(struct socket *sock, struct sockaddr *saddr, int len) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)22100.00%1100.00%
Total22100.00%1100.00%

EXPORT_SYMBOL(sock_no_bind);
int sock_no_connect(struct socket *sock, struct sockaddr *saddr, int len, int flags) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)25100.00%1100.00%
Total25100.00%1100.00%

EXPORT_SYMBOL(sock_no_connect);
int sock_no_socketpair(struct socket *sock1, struct socket *sock2) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)19100.00%1100.00%
Total19100.00%1100.00%

EXPORT_SYMBOL(sock_no_socketpair);
int sock_no_accept(struct socket *sock, struct socket *newsock, int flags, bool kern) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2288.00%150.00%
David Howells312.00%150.00%
Total25100.00%2100.00%

EXPORT_SYMBOL(sock_no_accept);
int sock_no_getname(struct socket *sock, struct sockaddr *saddr, int *len, int peer) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)26100.00%1100.00%
Total26100.00%1100.00%

EXPORT_SYMBOL(sock_no_getname);
unsigned int sock_no_poll(struct file *file, struct socket *sock, poll_table *pt) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)23100.00%3100.00%
Total23100.00%3100.00%

EXPORT_SYMBOL(sock_no_poll);
int sock_no_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)22100.00%1100.00%
Total22100.00%1100.00%

EXPORT_SYMBOL(sock_no_ioctl);
int sock_no_listen(struct socket *sock, int backlog) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)17100.00%1100.00%
Total17100.00%1100.00%

EXPORT_SYMBOL(sock_no_listen);
int sock_no_shutdown(struct socket *sock, int how) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)17100.00%1100.00%
Total17100.00%1100.00%

EXPORT_SYMBOL(sock_no_shutdown);
int sock_no_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2793.10%133.33%
David S. Miller13.45%133.33%
Linus Torvalds13.45%133.33%
Total29100.00%3100.00%

EXPORT_SYMBOL(sock_no_setsockopt);
int sock_no_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2893.33%150.00%
Linus Torvalds26.67%150.00%
Total30100.00%2100.00%

EXPORT_SYMBOL(sock_no_getsockopt);
int sock_no_sendmsg(struct socket *sock, struct msghdr *m, size_t len) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2090.91%266.67%
Stephen Hemminger29.09%133.33%
Total22100.00%3100.00%

EXPORT_SYMBOL(sock_no_sendmsg);
int sock_no_sendmsg_locked(struct sock *sk, struct msghdr *m, size_t len) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Tom Herbert22100.00%1100.00%
Total22100.00%1100.00%

EXPORT_SYMBOL(sock_no_sendmsg_locked);
int sock_no_recvmsg(struct socket *sock, struct msghdr *m, size_t len, int flags) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2496.00%375.00%
Stephen Hemminger14.00%125.00%
Total25100.00%4100.00%

EXPORT_SYMBOL(sock_no_recvmsg);
int sock_no_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma) { /* Mirror missing mmap method error code */ return -ENODEV; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)25100.00%1100.00%
Total25100.00%1100.00%

EXPORT_SYMBOL(sock_no_mmap);
ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags) { ssize_t res; struct msghdr msg = {.msg_flags = flags}; struct kvec iov; char *kaddr = kmap(page); iov.iov_base = kaddr + offset; iov.iov_len = size; res = kernel_sendmsg(sock, &msg, &iov, 1, size); kunmap(page); return res; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds7482.22%150.00%
Al Viro1617.78%150.00%
Total90100.00%2100.00%

EXPORT_SYMBOL(sock_no_sendpage);
ssize_t sock_no_sendpage_locked(struct sock *sk, struct page *page, int offset, size_t size, int flags) { ssize_t res; struct msghdr msg = {.msg_flags = flags}; struct kvec iov; char *kaddr = kmap(page); iov.iov_base = kaddr + offset; iov.iov_len = size; res = kernel_sendmsg_locked(sk, &msg, &iov, 1, size); kunmap(page); return res; }

Contributors

PersonTokensPropCommitsCommitProp
Tom Herbert90100.00%1100.00%
Total90100.00%1100.00%

EXPORT_SYMBOL(sock_no_sendpage_locked); /* * Default Socket Callbacks */
static void sock_def_wakeup(struct sock *sk) { struct socket_wq *wq; rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); if (skwq_has_sleeper(wq)) wake_up_interruptible_all(&wq->wait); rcu_read_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2656.52%562.50%
Eric Dumazet1839.13%112.50%
Herbert Xu12.17%112.50%
Adrian Bunk12.17%112.50%
Total46100.00%8100.00%


static void sock_def_error_report(struct sock *sk) { struct socket_wq *wq; rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); if (skwq_has_sleeper(wq)) wake_up_interruptible_poll(&wq->wait, POLLERR); sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); rcu_read_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3256.14%444.44%
Eric Dumazet1933.33%111.11%
Davide Libenzi35.26%111.11%
Adrian Bunk11.75%111.11%
Herbert Xu11.75%111.11%
Pavel Emelyanov11.75%111.11%
Total57100.00%9100.00%


static void sock_def_readable(struct sock *sk) { struct socket_wq *wq; rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); if (skwq_has_sleeper(wq)) wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND); sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); rcu_read_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3250.79%545.45%
Eric Dumazet2133.33%218.18%
Davide Libenzi711.11%19.09%
Herbert Xu11.59%19.09%
Pavel Emelyanov11.59%19.09%
Adrian Bunk11.59%19.09%
Total63100.00%11100.00%


static void sock_def_write_space(struct sock *sk) { struct socket_wq *wq; rcu_read_lock(); /* Do not wake up a writer until he can make "significant" * progress. --DaveM */ if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { wq = rcu_dereference(sk->sk_wq); if (skwq_has_sleeper(wq)) wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | POLLWRNORM | POLLWRBAND); /* Should agree with poll, otherwise some programs break */ if (sock_writeable(sk)) sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); } rcu_read_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5460.00%646.15%
Eric Dumazet2325.56%17.69%
Davide Libenzi77.78%17.69%
Arnaldo Carvalho de Melo22.22%17.69%
Adrian Bunk11.11%17.69%
Elena Reshetova11.11%17.69%
Pavel Emelyanov11.11%17.69%
Herbert Xu11.11%17.69%
Total90100.00%13100.00%


static void sock_def_destruct(struct sock *sk) { }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)880.00%133.33%
Adrian Bunk110.00%133.33%
David S. Miller110.00%133.33%
Total10100.00%3100.00%


void sk_send_sigurg(struct sock *sk) { if (sk->sk_socket && sk->sk_socket->file) if (send_sigurg(&sk->sk_socket->file->f_owner)) sk_wake_async(sk, SOCK_WAKE_URG, POLL_PRI); }

Contributors

PersonTokensPropCommitsCommitProp
James Morris4191.11%133.33%
Arnaldo Carvalho de Melo36.67%133.33%
Pavel Emelyanov12.22%133.33%
Total45100.00%3100.00%

EXPORT_SYMBOL(sk_send_sigurg);
void sk_reset_timer(struct sock *sk, struct timer_list* timer, unsigned long expires) { if (!mod_timer(timer, expires)) sock_hold(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo34100.00%1100.00%
Total34100.00%1100.00%

EXPORT_SYMBOL(sk_reset_timer);
void sk_stop_timer(struct sock *sk, struct timer_list* timer) { if (del_timer(timer)) __sock_put(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo27100.00%1100.00%
Total27100.00%1100.00%

EXPORT_SYMBOL(sk_stop_timer);
void sock_init_data(struct socket *sock, struct sock *sk) { sk_init_common(sk); sk->sk_send_head = NULL; init_timer(&sk->sk_timer); sk->sk_allocation = GFP_KERNEL; sk->sk_rcvbuf = sysctl_rmem_default; sk->sk_sndbuf = sysctl_wmem_default; sk->sk_state = TCP_CLOSE; sk_set_socket(sk, sock); sock_set_flag(sk, SOCK_ZAPPED); if (sock) { sk->sk_type = sock->type; sk->sk_wq = sock->wq; sock->sk = sk; sk->sk_uid = SOCK_INODE(sock)->i_uid; } else { sk->sk_wq = NULL; sk->sk_uid = make_kuid(sock_net(sk)->user_ns, 0); } rwlock_init(&sk->sk_callback_lock); if (sk->sk_kern_sock) lockdep_set_class_and_name( &sk->sk_callback_lock, af_kern_callback_keys + sk->sk_family, af_family_kern_clock_key_strings[sk->sk_family]); else lockdep_set_class_and_name( &sk->sk_callback_lock, af_callback_keys + sk->sk_family, af_family_clock_key_strings[sk->sk_family]); sk->sk_state_change = sock_def_wakeup; sk->sk_data_ready = sock_def_readable; sk->sk_write_space = sock_def_write_space; sk->sk_error_report = sock_def_error_report; sk->sk_destruct = sock_def_destruct; sk->sk_frag.page = NULL; sk->sk_frag.offset = 0; sk->sk_peek_off = -1; sk->sk_peer_pid = NULL; sk->sk_peer_cred = NULL; sk->sk_write_pending = 0; sk->sk_rcvlowat = 1; sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_stamp = SK_DEFAULT_STAMP; atomic_set(&sk->sk_zckey, 0); #ifdef CONFIG_NET_RX_BUSY_POLL sk->sk_napi_id = 0; sk->sk_ll_usec = sysctl_net_busy_read; #endif sk->sk_max_pacing_rate = ~0U; sk->sk_pacing_rate = ~0U; sk->sk_incoming_cpu = -1; /* * Before updating sk_refcnt, we must commit prior changes to memory * (Documentation/RCU/rculist_nulls.txt for details) */ smp_wmb(); refcount_set(&sk->sk_refcnt, 1); atomic_set(&sk->sk_drops, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)13938.61%922.50%
Arnaldo Carvalho de Melo4011.11%512.50%
Eric Dumazet328.89%615.00%
Lorenzo Colitti298.06%12.50%
David Howells287.78%12.50%
Eliezer Tamir164.44%37.50%
Ingo Molnar133.61%12.50%
Willem de Bruijn102.78%12.50%
Wang Chen102.78%12.50%
Peter Zijlstra82.22%12.50%
Thomas Graf71.94%12.50%
Pavel Emelyanov71.94%12.50%
David S. Miller61.67%25.00%
Andrew Morton41.11%12.50%
Eric W. Biedermann41.11%12.50%
Andi Kleen30.83%12.50%
Paolo Abeni20.56%25.00%
Elena Reshetova10.28%12.50%
Américo Wang10.28%12.50%
Total360100.00%40100.00%

EXPORT_SYMBOL(sock_init_data);
void lock_sock_nested(struct sock *sk, int subclass) { might_sleep(); spin_lock_bh(&sk->sk_lock.slock); if (sk->sk_lock.owned) __lock_sock(sk); sk->sk_lock.owned = 1; spin_unlock(&sk->sk_lock.slock); /* * The sk_lock has mutex_lock() semantics here: */ mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_); local_bh_enable(); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo5064.94%125.00%
Ingo Molnar2025.97%125.00%
Peter Zijlstra56.49%125.00%
John Heffner22.60%125.00%
Total77100.00%4100.00%

EXPORT_SYMBOL(lock_sock_nested);
void release_sock(struct sock *sk) { spin_lock_bh(&sk->sk_lock.slock); if (sk->sk_backlog.tail) __release_sock(sk); /* Warning : release_cb() might need to release sk ownership, * ie call sock_release_ownership(sk) before us. */ if (sk->sk_prot->release_cb) sk->sk_prot->release_cb(sk); sock_release_ownership(sk); if (waitqueue_active(&sk->sk_lock.wq)) wake_up(&sk->sk_lock.wq); spin_unlock_bh(&sk->sk_lock.slock); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo6776.14%133.33%
Eric Dumazet2123.86%266.67%
Total88100.00%3100.00%

EXPORT_SYMBOL(release_sock); /** * lock_sock_fast - fast version of lock_sock * @sk: socket * * This version should be used for very small section, where process wont block * return false if fast path is taken: * * sk_lock.slock locked, owned = 0, BH disabled * * return true if slow path is taken: * * sk_lock.slock unlocked, owned = 1, BH enabled */
bool lock_sock_fast(struct sock *sk) { might_sleep(); spin_lock_bh(&sk->sk_lock.slock); if (!sk->sk_lock.owned) /* * Note : We must disable BH */ return false; __lock_sock(sk); sk->sk_lock.owned = 1; spin_unlock(&sk->sk_lock.slock); /* * The sk_lock has mutex_lock() semantics here: */ mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_); local_bh_enable(); return true; }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet82100.00%1100.00%
Total82100.00%1100.00%

EXPORT_SYMBOL(lock_sock_fast);
int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) { struct timeval tv; if (!sock_flag(sk, SOCK_TIMESTAMP)) sock_enable_timestamp(sk, SOCK_TIMESTAMP); tv = ktime_to_timeval(sk->sk_stamp); if (tv.tv_sec == -1) return -ENOENT; if (tv.tv_sec == 0) { sk->sk_stamp = ktime_get_real(); tv = ktime_to_timeval(sk->sk_stamp); } return copy_to_user(userstamp, &tv, sizeof(tv)) ? -EFAULT : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen7370.19%125.00%
Eric Dumazet2826.92%125.00%
Patrick Ohly21.92%125.00%
Linus Torvalds10.96%125.00%
Total104100.00%4100.00%

EXPORT_SYMBOL(sock_get_timestamp);
int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) { struct timespec ts; if (!sock_flag(sk, SOCK_TIMESTAMP)) sock_enable_timestamp(sk, SOCK_TIMESTAMP); ts = ktime_to_timespec(sk->sk_stamp); if (ts.tv_sec == -1) return -ENOENT; if (ts.tv_sec == 0) { sk->sk_stamp = ktime_get_real(); ts = ktime_to_timespec(sk->sk_stamp); } return copy_to_user(userstamp, &ts, sizeof(ts)) ? -EFAULT : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet10298.08%150.00%
Patrick Ohly21.92%150.00%
Total104100.00%2100.00%

EXPORT_SYMBOL(sock_get_timestampns);
void sock_enable_timestamp(struct sock *sk, int flag) { if (!sock_flag(sk, flag)) { unsigned long previous_flags = sk->sk_flags; sock_set_flag(sk, flag); /* * we just set one of the two flags which require net * time stamping, but time stamping might have been on * already because of the other one */ if (sock_needs_netstamp(sk) && !(previous_flags & SK_FLAGS_TIMESTAMP)) net_enable_timestamp(); } }

Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen2848.28%120.00%
Eric Dumazet1322.41%120.00%
Patrick Ohly1017.24%120.00%
Hannes Frederic Sowa58.62%120.00%
Patrick McHardy23.45%120.00%
Total58100.00%5100.00%


int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, int level, int type) { struct sock_exterr_skb *serr; struct sk_buff *skb; int copied, err; err = -EAGAIN; skb = sock_dequeue_err_skb(sk); if (skb == NULL) goto out; copied = skb->len; if (copied > len) { msg->msg_flags |= MSG_TRUNC; copied = len; } err = skb_copy_datagram_msg(skb, 0, msg, copied); if (err) goto out_free_skb; sock_recv_timestamp(msg, sk, skb); serr = SKB_EXT_ERR(skb); put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee); msg->msg_flags |= MSG_ERRQUEUE; err = copied; out_free_skb: kfree_skb(skb); out: return err; }

Contributors

PersonTokensPropCommitsCommitProp
Richard Cochran16198.77%133.33%
David S. Miller10.61%133.33%
Willem de Bruijn10.61%133.33%
Total163100.00%3100.00%

EXPORT_SYMBOL(sock_recv_errqueue); /* * Get a socket option on an socket. * * FIX: POSIX 1003.1g is very ambiguous here. It states that * asynchronous errors should be reported by getsockopt. We assume * this means if you specify SO_ERROR (otherwise whats the point of it). */
int sock_common_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo53100.00%1100.00%
Total53100.00%1100.00%

EXPORT_SYMBOL(sock_common_getsockopt); #ifdef CONFIG_COMPAT
int compat_sock_common_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; if (sk->sk_prot->compat_getsockopt != NULL) return sk->sk_prot->compat_getsockopt(sk, level, optname, optval, optlen); return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen); }

Contributors

PersonTokensPropCommitsCommitProp
Dmitry Mishin7896.30%133.33%
Arnaldo Carvalho de Melo22.47%133.33%
Johannes Berg11.23%133.33%
Total81100.00%3100.00%

EXPORT_SYMBOL(compat_sock_common_getsockopt); #endif
int sock_common_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct sock *sk = sock->sk; int addr_len = 0; int err; err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, &addr_len); if (err >= 0) msg->msg_namelen = addr_len; return err; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo80100.00%1100.00%
Total80100.00%1100.00%

EXPORT_SYMBOL(sock_common_recvmsg); /* * Set socket options on an inet socket. */
int sock_common_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo5198.08%150.00%
David S. Miller11.92%150.00%
Total52100.00%2100.00%

EXPORT_SYMBOL(sock_common_setsockopt); #ifdef CONFIG_COMPAT
int compat_sock_common_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; if (sk->sk_prot->compat_setsockopt != NULL) return sk->sk_prot->compat_setsockopt(sk, level, optname, optval, optlen); return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen); }

Contributors

PersonTokensPropCommitsCommitProp
Dmitry Mishin7796.25%133.33%
Arnaldo Carvalho de Melo22.50%133.33%
David S. Miller11.25%133.33%
Total80100.00%3100.00%

EXPORT_SYMBOL(compat_sock_common_setsockopt); #endif
void sk_common_release(struct sock *sk) { if (sk->sk_prot->destroy) sk->sk_prot->destroy(sk); /* * Observation: when sock_common_release is called, processes have * no access to socket. But net still has. * Step one, detach it from networking: * * A. Remove from hash tables. */ sk->sk_prot->unhash(sk); /* * In this point socket cannot receive new packets, but it is possible * that some packets are in flight because some CPU runs receiver and * did hash table lookup before we unhashed socket. They will achieve * receive queue and will be purged by socket destructor. * * Also we still have packets pending on receive queue and probably, * our own packets waiting in device queues. sock_destroy will drain * receive queue, but transmitted packets will delay socket destruction * until the last reference will be released. */ sock_orphan(sk); xfrm_sk_free_policy(sk); sk_refcnt_debug_release(sk); sock_put(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo58100.00%2100.00%
Total58100.00%2100.00%

EXPORT_SYMBOL(sk_common_release);
void sk_get_meminfo(const struct sock *sk, u32 *mem) { memset(mem, 0, sizeof(*mem) * SK_MEMINFO_VARS); mem[SK_MEMINFO_RMEM_ALLOC] = sk_rmem_alloc_get(sk); mem[SK_MEMINFO_RCVBUF] = sk->sk_rcvbuf; mem[SK_MEMINFO_WMEM_ALLOC] = sk_wmem_alloc_get(sk); mem[SK_MEMINFO_SNDBUF] = sk->sk_sndbuf; mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc; mem[SK_MEMINFO_WMEM_QUEUED] = sk->sk_wmem_queued; mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc); mem[SK_MEMINFO_BACKLOG] = sk->sk_backlog.len; mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops); }

Contributors

PersonTokensPropCommitsCommitProp
Joshua Hunt123100.00%1100.00%
Total123100.00%1100.00%

#ifdef CONFIG_PROC_FS #define PROTO_INUSE_NR 64 /* should be enough for the first time */ struct prot_inuse { int val[PROTO_INUSE_NR]; }; static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR); #ifdef CONFIG_NET_NS
void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) { __this_cpu_add(net->core.inuse->val[prot->inuse_idx], val); }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov3391.67%150.00%
Eric Dumazet38.33%150.00%
Total36100.00%2100.00%

EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
int sock_prot_inuse_get(struct net *net, struct proto *prot) { int cpu, idx = prot->inuse_idx; int res = 0; for_each_possible_cpu(cpu) res += per_cpu_ptr(net->core.inuse, cpu)->val[idx]; return res >= 0 ? res : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov60100.00%1100.00%
Total60100.00%1100.00%

EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
static int __net_init sock_inuse_init_net(struct net *net) { net->core.inuse = alloc_percpu(struct prot_inuse); return net->core.inuse ? 0 : -ENOMEM; }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov3597.22%150.00%
Alexey Dobriyan12.78%150.00%
Total36100.00%2100.00%


static void __net_exit sock_inuse_exit_net(struct net *net) { free_percpu(net->core.inuse); }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov2095.24%150.00%
Alexey Dobriyan14.76%150.00%
Total21100.00%2100.00%

static struct pernet_operations net_inuse_ops = { .init = sock_inuse_init_net, .exit = sock_inuse_exit_net, };
static __init int net_inuse_init(void) { if (register_pernet_subsys(&net_inuse_ops)) panic("Cannot initialize net inuse counters"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov25100.00%1100.00%
Total25100.00%1100.00%

core_initcall(net_inuse_init); #else static DEFINE_PER_CPU(struct prot_inuse, prot_inuse);
void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) { __this_cpu_add(prot_inuse.val[prot->inuse_idx], val); }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov2990.62%266.67%
Eric Dumazet39.38%133.33%
Total32100.00%3100.00%

EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
int sock_prot_inuse_get(struct net *net, struct proto *prot) { int cpu, idx = prot->inuse_idx; int res = 0; for_each_possible_cpu(cpu) res += per_cpu(prot_inuse, cpu).val[idx]; return res >= 0 ? res : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov56100.00%2100.00%
Total56100.00%2100.00%

EXPORT_SYMBOL_GPL(sock_prot_inuse_get); #endif
static void assign_proto_idx(struct proto *prot) { prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR); if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) { pr_err("PROTO_INUSE_NR exhausted\n"); return; } set_bit(prot->inuse_idx, proto_inuse_idx); }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov5198.08%150.00%
Joe Perches11.92%150.00%
Total52100.00%2100.00%


static void release_proto_idx(struct proto *prot) { if (prot->inuse_idx != PROTO_INUSE_NR - 1) clear_bit(prot->inuse_idx, proto_inuse_idx); }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov30100.00%1100.00%
Total30100.00%1100.00%

#else
static inline void assign_proto_idx(struct proto *prot) { }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov11100.00%1100.00%
Total11100.00%1100.00%


static inline void release_proto_idx(struct proto *prot) { }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov11100.00%1100.00%
Total11100.00%1100.00%

#endif
static void req_prot_cleanup(struct request_sock_ops *rsk_prot) { if (!rsk_prot) return; kfree(rsk_prot->slab_name); rsk_prot->slab_name = NULL; kmem_cache_destroy(rsk_prot->slab); rsk_prot->slab = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet2558.14%228.57%
Pavel Emelyanov716.28%114.29%
Arnaldo Carvalho de Melo716.28%342.86%
Hideaki Yoshifuji / 吉藤英明49.30%114.29%
Total43100.00%7100.00%


static int req_prot_init(const struct proto *prot) { struct request_sock_ops *rsk_prot = prot->rsk_prot; if (!rsk_prot) return 0; rsk_prot->slab_name = kasprintf(GFP_KERNEL, "request_sock_%s", prot->name); if (!rsk_prot->slab_name) return -ENOMEM; rsk_prot->slab = kmem_cache_create(rsk_prot->slab_name, rsk_prot->obj_size, 0, prot->slab_flags, NULL); if (!rsk_prot->slab) { pr_crit("%s: Can't create request sock SLAB cache!\n", prot->name); return -ENOMEM; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet7572.82%240.00%
Arnaldo Carvalho de Melo1413.59%120.00%
Catalin Marinas98.74%120.00%
Alexey Dobriyan54.85%120.00%
Total103100.00%5100.00%


int proto_register(struct proto *prot, int alloc_slab) { if (alloc_slab) { prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0, SLAB_HWCACHE_ALIGN | prot->slab_flags, NULL); if (prot->slab == NULL) { pr_crit("%s: Can't create sock SLAB cache!\n", prot->name); goto out; } if (req_prot_init(prot)) goto out_free_request_sock_slab; if (prot->twsk_prot != NULL) { prot->twsk_prot->twsk_slab_name = kasprintf(GFP_KERNEL, "tw_sock_%s", prot->name); if (prot->twsk_prot->twsk_slab_name == NULL) goto out_free_request_sock_slab; prot->twsk_prot->twsk_slab = kmem_cache_create(prot->twsk_prot->twsk_slab_name, prot->twsk_prot->twsk_obj_size, 0, prot->slab_flags, NULL); if (prot->twsk_prot->twsk_slab == NULL) goto out_free_timewait_sock_slab_name; } } mutex_lock(&proto_list_mutex); list_add(&prot->node, &proto_list); assign_proto_idx(prot); mutex_unlock(&proto_list_mutex); return 0; out_free_timewait_sock_slab_name: kfree(prot->twsk_prot->twsk_slab_name); out_free_request_sock_slab: req_prot_cleanup(prot->rsk_prot); kmem_cache_destroy(prot->slab); prot->slab = NULL; out: return -ENOBUFS; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo14463.16%535.71%
Eric Dumazet3917.11%214.29%
Catalin Marinas229.65%17.14%
Pavel Emelyanov114.82%214.29%
Alexey Dobriyan52.19%17.14%
Glauber de Oliveira Costa41.75%17.14%
Hideaki Yoshifuji / 吉藤英明20.88%17.14%
Joe Perches10.44%17.14%
Total228100.00%14100.00%

EXPORT_SYMBOL(proto_register);
void proto_unregister(struct proto *prot) { mutex_lock(&proto_list_mutex); release_proto_idx(prot); list_del(&prot->node); mutex_unlock(&proto_list_mutex); kmem_cache_destroy(prot->slab); prot->slab = NULL; req_prot_cleanup(prot->rsk_prot); if (prot->twsk_prot != NULL && prot->twsk_prot->twsk_slab != NULL) { kmem_cache_destroy(prot->twsk_prot->twsk_slab); kfree(prot->twsk_prot->twsk_slab_name); prot->twsk_prot->twsk_slab = NULL; } }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo7373.74%550.00%
Patrick McHardy1212.12%110.00%
Pavel Emelyanov55.05%110.00%
Glauber de Oliveira Costa44.04%110.00%
Catalin Marinas44.04%110.00%
Eric Dumazet11.01%110.00%
Total99100.00%10100.00%

EXPORT_SYMBOL(proto_unregister); #ifdef CONFIG_PROC_FS
static void *proto_seq_start(struct seq_file *seq, loff_t *pos) __acquires(proto_list_mutex) { mutex_lock(&proto_list_mutex); return seq_list_start_head(&proto_list, *pos); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo2672.22%125.00%
Pavel Emelyanov411.11%125.00%
Eric Dumazet38.33%125.00%
Glauber de Oliveira Costa38.33%125.00%
Total36100.00%4100.00%


static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos) { return seq_list_next(v, &proto_list, pos); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo2580.65%150.00%
Pavel Emelyanov619.35%150.00%
Total31100.00%2100.00%


static void proto_seq_stop(struct seq_file *seq, void *v) __releases(proto_list_mutex) { mutex_unlock(&proto_list_mutex); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo1976.00%133.33%
Glauber de Oliveira Costa312.00%133.33%
Eric Dumazet312.00%133.33%
Total25100.00%3100.00%


static char proto_method_implemented(const void *method) { return method == NULL ? 'n' : 'y'; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo20100.00%1100.00%
Total20100.00%1100.00%


static long sock_prot_memory_allocated(struct proto *proto) { return proto->memory_allocated != NULL ? proto_memory_allocated(proto) : -1L; }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa26100.00%1100.00%
Total26100.00%1100.00%


static char *sock_prot_memory_pressure(struct proto *proto) { return proto->memory_pressure != NULL ? proto_memory_pressure(proto) ? "yes" : "no" : "NI"; }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa30100.00%1100.00%
Total30100.00%1100.00%


static void proto_seq_printf(struct seq_file *seq, struct proto *proto) { seq_printf(seq, "%-9s %4u %6d %6ld %-3s %6u %-3s %-10s " "%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n", proto->name, proto->obj_size, sock_prot_inuse_get(seq_file_net(seq), proto), sock_prot_memory_allocated(proto), sock_prot_memory_pressure(proto), proto->max_header, proto->slab == NULL ? "no" : "yes", module_name(proto->owner), proto_method_implemented(proto->close), proto_method_implemented(proto->connect), proto_method_implemented(proto->disconnect), proto_method_implemented(proto->accept), proto_method_implemented(proto->ioctl), proto_method_implemented(proto->init), proto_method_implemented(proto->destroy), proto_method_implemented(proto->shutdown), proto_method_implemented(proto->setsockopt), proto_method_implemented(proto->getsockopt), proto_method_implemented(proto->sendmsg), proto_method_implemented(proto->recvmsg), proto_method_implemented(proto->sendpage), proto_method_implemented(proto->bind), proto_method_implemented(proto->backlog_rcv), proto_method_implemented(proto->hash), proto_method_implemented(proto->unhash), proto_method_implemented(proto->get_port), proto_method_implemented(proto->enter_memory_pressure)); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo19594.66%125.00%
Eric Dumazet73.40%250.00%
Glauber de Oliveira Costa41.94%125.00%
Total206100.00%4100.00%


static int proto_seq_show(struct seq_file *seq, void *v) { if (v == &proto_list) seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s", "protocol", "size", "sockets", "memory", "press", "maxhdr", "slab", "module", "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n"); else proto_seq_printf(seq, list_entry(v, struct proto, node)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo5684.85%150.00%
Pavel Emelyanov1015.15%150.00%
Total66100.00%2100.00%

static const struct seq_operations proto_seq_ops = { .start = proto_seq_start, .next = proto_seq_next, .stop = proto_seq_stop, .show = proto_seq_show, };
static int proto_seq_open(struct inode *inode, struct file *file) { return seq_open_net(inode, file, &proto_seq_ops, sizeof(struct seq_net_private)); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo2472.73%150.00%
Eric Dumazet927.27%150.00%
Total33100.00%2100.00%

static const struct file_operations proto_seq_fops = { .owner = THIS_MODULE, .open = proto_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release_net, };
static __net_init int proto_init_net(struct net *net) { if (!proc_create("protocols", S_IRUGO, net->proc_net, &proto_seq_fops)) return -ENOMEM; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo1747.22%133.33%
Eric Dumazet1438.89%133.33%
Gao Feng513.89%133.33%
Total36100.00%3100.00%


static __net_exit void proto_exit_net(struct net *net) { remove_proc_entry("protocols", net->proc_net); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet1676.19%150.00%
Gao Feng523.81%150.00%
Total21100.00%2100.00%

static __net_initdata struct pernet_operations proto_net_ops = { .init = proto_init_net, .exit = proto_exit_net, };
static int __init proto_init(void) { return register_pernet_subsys(&proto_net_ops); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet16100.00%1100.00%
Total16100.00%1100.00%

subsys_initcall(proto_init); #endif /* PROC_FS */ #ifdef CONFIG_NET_RX_BUSY_POLL
bool sk_busy_loop_end(void *p, unsigned long start_time) { struct sock *sk = p; return !skb_queue_empty(&sk->sk_receive_queue) || sk_busy_loop_timeout(sk, start_time); }

Contributors

PersonTokensPropCommitsCommitProp
Sridhar Samudrala37100.00%1100.00%
Total37100.00%1100.00%

EXPORT_SYMBOL(sk_busy_loop_end); #endif /* CONFIG_NET_RX_BUSY_POLL */

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)258418.50%7116.90%
Eric Dumazet208214.90%7618.10%
Arnaldo Carvalho de Melo168312.05%245.71%
Pavel Emelyanov9146.54%225.24%
Paolo Abeni5854.19%30.71%
Willem de Bruijn4072.91%102.38%
Eric W. Biedermann3232.31%112.62%
Denys Vlasenko3032.17%10.24%
Hideo Aoki2701.93%10.24%
David S. Miller2551.83%143.33%
Andi Kleen2431.74%30.71%
Linus Torvalds1941.39%102.38%
Joshua Hunt1841.32%10.24%
Dmitry Mishin1801.29%20.48%
David Howells1771.27%10.24%
David Herrmann1751.25%10.24%
Craig Gallek1741.25%40.95%
Brian Haley1711.22%20.48%
Richard Cochran1691.21%10.24%
Ingo Molnar1631.17%40.95%
Tom Herbert1611.15%40.95%
Glauber de Oliveira Costa1471.05%40.95%
Mel Gorman1461.05%61.43%
Hannes Frederic Sowa1250.89%20.48%
Stephen Hemminger1020.73%61.43%
James Morris960.69%30.71%
Edward Hyunkoo Jee960.69%10.24%
Daniel Borkmann940.67%20.48%
Eliezer Tamir860.62%40.95%
Sridhar Samudrala830.59%20.48%
Soheil Hassas Yeganeh790.57%30.71%
Patrick Ohly780.56%10.24%
Johannes Weiner770.55%51.19%
samanthakumar750.54%20.48%
Neil Horman730.52%20.48%
Patrick McHardy640.46%30.71%
Alexei Starovoitov640.46%20.48%
Vasily Averin610.44%10.24%
Thomas Graf540.39%51.19%
Catherine Zhang480.34%20.48%
Vincent Bernat460.33%10.24%
Yi Zhu390.28%20.48%
Andrew Morton370.26%40.95%
Tóth László Attila350.25%10.24%
Catalin Marinas350.25%10.24%
Peter Zijlstra340.24%30.71%
Chenbo Feng330.24%10.24%
Jan Engelhardt330.24%30.71%
Johannes Berg310.22%30.71%
Herbert Pötzl290.21%10.24%
Lorenzo Colitti290.21%10.24%
Jacob E Keller280.20%10.24%
Al Viro220.16%30.71%
Alexander Duyck220.16%10.24%
Hideaki Yoshifuji / 吉藤英明220.16%40.95%
Elena Reshetova220.16%20.48%
Francis Yan210.15%10.24%
Christoph Hellwig200.14%10.24%
Américo Wang200.14%30.71%
Satoru Moriya190.14%10.24%
Herbert Xu180.13%40.95%
Gao Feng170.12%30.71%
Davide Libenzi170.12%10.24%
Joe Perches170.12%10.24%
Namhyung Kim160.11%10.24%
Peter P. Waskiewicz Jr140.10%10.24%
Tejun Heo140.10%20.48%
Ben Greear130.09%10.24%
Alexey Dobriyan120.09%20.48%
Julian Anastasov120.09%10.24%
Krishna Kumar110.08%10.24%
Vlastimil Babka110.08%10.24%
Michal Sekletar110.08%10.24%
Wang Chen100.07%10.24%
Hans Schillstrom100.07%10.24%
Sabrina Dubroca100.07%10.24%
Paul E. McKenney100.07%10.24%
Eugene Teo100.07%10.24%
Jarek Poplawski90.06%10.24%
Sowmini Varadhan90.06%10.24%
Octavian Purdila80.06%20.48%
Christoph Paasch80.06%10.24%
Ursula Braun70.05%10.24%
Vegard Nossum70.05%10.24%
Ben Hutchings70.05%10.24%
Steffen Klassert60.04%10.24%
Adrian Bunk60.04%20.48%
Nicolas Schichan50.04%10.24%
Shaohua Li40.03%10.24%
Arjan van de Ven30.02%20.48%
Eyal Birger30.02%10.24%
Frank Filz30.02%10.24%
Benjamin LaHaise30.02%10.24%
Clément Lecigne30.02%10.24%
Randy Dunlap30.02%10.24%
John Heffner20.01%10.24%
Lucas De Marchi20.01%10.24%
Masanari Iida20.01%10.24%
Ilpo Järvinen20.01%10.24%
Mika Kukkonen20.01%10.24%
Sasha Levin20.01%10.24%
Christoph Lameter20.01%10.24%
Dave Jones10.01%10.24%
Mauro Carvalho Chehab10.01%10.24%
Oliver Hartkopp10.01%10.24%
Hideaki Yoshifuji/吉藤英明10.01%10.24%
Venkat Yekkirala10.01%10.24%
Harvey Harrison10.01%10.24%
JoonSoo Kim10.01%10.24%
Rémi Denis-Courmont10.01%10.24%
Total13971100.00%420100.00%
Directory: net/core
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.