summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.ninka.net>2003-05-02 11:13:39 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2003-05-02 11:13:39 -0700
commit8bbb2b4199fad5ac700564f4fff59c38d78fa808 (patch)
treefb8bf30642a52ec1a428d7e119619fdd23621dc2
parentd7920faf65a0950ca18e75e4980ce967dab5b36e (diff)
parent8b97999a03d5b79c190be3b33859fa1d4bdab22d (diff)
Merge bk://kernel.bkbits.net/acme/net_family-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
-rw-r--r--drivers/net/pppoe.c13
-rw-r--r--drivers/net/pppox.c42
-rw-r--r--include/linux/if_pppox.h5
-rw-r--r--include/linux/net.h9
-rw-r--r--include/net/sock.h20
-rw-r--r--net/appletalk/ddp.c1
-rw-r--r--net/ax25/af_ax25.c4
-rw-r--r--net/bluetooth/bnep/sock.c1
-rw-r--r--net/bluetooth/hci_sock.c1
-rw-r--r--net/bluetooth/l2cap.c2
-rw-r--r--net/bluetooth/rfcomm/sock.c1
-rw-r--r--net/bluetooth/sco.c2
-rw-r--r--net/core/sock.c11
-rw-r--r--net/decnet/af_decnet.c3
-rw-r--r--net/econet/af_econet.c2
-rw-r--r--net/ipv4/af_inet.c5
-rw-r--r--net/ipv4/syncookies.c5
-rw-r--r--net/ipv4/tcp_minisocks.c1
-rw-r--r--net/ipv6/af_inet6.c5
-rw-r--r--net/ipv6/tcp_ipv6.c2
-rw-r--r--net/ipx/af_ipx.c1
-rw-r--r--net/irda/af_irda.c8
-rw-r--r--net/key/af_key.c5
-rw-r--r--net/llc/af_llc.c1
-rw-r--r--net/netlink/af_netlink.c3
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--net/packet/af_packet.c5
-rw-r--r--net/rose/af_rose.c2
-rw-r--r--net/sctp/ipv6.c2
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/socket.c80
-rw-r--r--net/unix/af_unix.c5
-rw-r--r--net/wanrouter/af_wanpipe.c2
-rw-r--r--net/x25/af_x25.c2
34 files changed, 121 insertions, 134 deletions
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index ba2ba6d5e179..9f1feff3538b 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -494,16 +494,21 @@ static int pppoe_create(struct socket *sock)
struct sock *sk;
struct pppox_opt *po;
- sk = pppox_sk_alloc(sock, PX_PROTO_OE, GFP_KERNEL, 1, NULL);
+ sk = sk_alloc(PF_PPPOX, GFP_KERNEL, 1, NULL);
if (!sk)
goto out;
+ sock_init_data(sock, sk);
+ sk_set_owner(sk, THIS_MODULE);
sock->state = SS_UNCONNECTED;
sock->ops = &pppoe_ops;
sk->backlog_rcv = pppoe_rcv_core;
sk->state = PPPOX_NONE;
sk->type = SOCK_STREAM;
+ sk->family = PF_PPPOX;
+ sk->protocol = PX_PROTO_OE;
+ sk->destruct = pppoe_sk_free;
po = pppox_sk(sk) = kmalloc(sizeof(*po), GFP_KERNEL);
if (!po)
@@ -1062,10 +1067,12 @@ static struct file_operations pppoe_seq_fops = {
};
#endif /* CONFIG_PROC_FS */
-/* ->release and ->ioctl are set at pppox_create */
+/* ->ioctl are set at pppox_create */
struct proto_ops pppoe_ops = {
.family = AF_PPPOX,
+ .owner = THIS_MODULE,
+ .release = pppoe_release,
.bind = sock_no_bind,
.connect = pppoe_connect,
.socketpair = sock_no_socketpair,
@@ -1084,8 +1091,6 @@ struct proto_ops pppoe_ops = {
struct pppox_proto pppoe_proto = {
.create = pppoe_create,
.ioctl = pppoe_ioctl,
- .release = pppoe_release,
- .sk_free = pppoe_sk_free,
.owner = THIS_MODULE,
};
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c
index fd1838f36da3..a5633d50c35a 100644
--- a/drivers/net/pppox.c
+++ b/drivers/net/pppox.c
@@ -64,45 +64,9 @@ void pppox_unbind_sock(struct sock *sk)
}
}
-static int pppox_release(struct socket *sock)
-{
- struct sock *sk = sock->sk;
- int rc = pppox_protos[sk->protocol]->release(sock);
-
- module_put(pppox_protos[sk->protocol]->owner);
- return rc;
-}
-
-static void pppox_sk_free(struct sock *sk)
-{
- pppox_protos[sk->protocol]->sk_free(sk);
- module_put(pppox_protos[sk->protocol]->owner);
-}
-
-struct sock *pppox_sk_alloc(struct socket *sock, int protocol, int priority,
- int zero_it, kmem_cache_t *slab)
-{
- struct sock *sk = NULL;
-
- if (!try_module_get(pppox_protos[protocol]->owner))
- goto out;
-
- sk = sk_alloc(PF_PPPOX, priority, zero_it, slab);
- if (sk) {
- sock_init_data(sock, sk);
- sk->family = PF_PPPOX;
- sk->protocol = protocol;
- sk->destruct = pppox_sk_free;
- } else
- module_put(pppox_protos[protocol]->owner);
-out:
- return sk;
-}
-
EXPORT_SYMBOL(register_pppox_proto);
EXPORT_SYMBOL(unregister_pppox_proto);
EXPORT_SYMBOL(pppox_unbind_sock);
-EXPORT_SYMBOL(pppox_sk_alloc);
static int pppox_ioctl(struct socket* sock, unsigned int cmd,
unsigned long arg)
@@ -156,12 +120,10 @@ static int pppox_create(struct socket *sock, int protocol)
rc = pppox_protos[protocol]->create(sock);
if (!rc) {
/* We get to set the ioctl handler. */
- /* And the release handler, for module refcounting */
/* For everything else, pppox is just a shell. */
sock->ops->ioctl = pppox_ioctl;
- sock->ops->release = pppox_release;
- } else
- module_put(pppox_protos[protocol]->owner);
+ }
+ module_put(pppox_protos[protocol]->owner);
out:
return rc;
}
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 117357b14483..78ffd78ddb9e 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -140,8 +140,6 @@ struct pppox_proto {
int (*create)(struct socket *sock);
int (*ioctl)(struct socket *sock, unsigned int cmd,
unsigned long arg);
- int (*release)(struct socket *sock);
- void (*sk_free)(struct sock *sk);
struct module *owner;
};
@@ -150,9 +148,6 @@ extern void unregister_pppox_proto(int proto_num);
extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
extern int pppox_channel_ioctl(struct ppp_channel *pc, unsigned int cmd,
unsigned long arg);
-extern struct sock *pppox_sk_alloc(struct socket *sock, int protocol,
- int priority, int zero_it,
- kmem_cache_t *slab);
/* PPPoX socket states */
enum {
diff --git a/include/linux/net.h b/include/linux/net.h
index 8b012430f49d..04bd681473db 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -89,9 +89,11 @@ struct page;
struct kiocb;
struct sockaddr;
struct msghdr;
+struct module;
struct proto_ops {
int family;
+ struct module *owner;
int (*release) (struct socket *sock);
int (*bind) (struct socket *sock,
struct sockaddr *umyaddr,
@@ -127,8 +129,6 @@ struct proto_ops {
int offset, size_t size, int flags);
};
-struct module;
-
struct net_proto_family {
int family;
int (*create)(struct socket *sock, int protocol);
@@ -140,9 +140,6 @@ struct net_proto_family {
struct module *owner;
};
-extern int net_family_get(int family);
-extern void net_family_put(int family);
-
struct iovec;
extern int sock_wake_async(struct socket *sk, int how, int band);
@@ -227,7 +224,7 @@ SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_are
\
static struct proto_ops name##_ops = { \
.family = fam, \
- \
+ .owner = THIS_MODULE, \
.release = __lock_##name##_release, \
.bind = __lock_##name##_bind, \
.connect = __lock_##name##_connect, \
diff --git a/include/net/sock.h b/include/net/sock.h
index 4f5b79f30880..53639300bc3c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -43,7 +43,7 @@
#include <linux/config.h>
#include <linux/timer.h>
#include <linux/cache.h>
-
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h> /* struct sk_buff */
#include <linux/security.h>
@@ -197,6 +197,7 @@ struct sock {
void *user_data;
/* Callbacks */
+ struct module *owner;
void (*state_change)(struct sock *sk);
void (*data_ready)(struct sock *sk,int bytes);
void (*write_space)(struct sock *sk);
@@ -270,6 +271,23 @@ struct proto {
} stats[NR_CPUS];
};
+static __inline__ void sk_set_owner(struct sock *sk, struct module *owner)
+{
+ /*
+ * One should use sk_set_owner just once, after struct sock creation,
+ * be it shortly after sk_alloc or after a function that returns a new
+ * struct sock (and that down the call chain called sk_alloc), e.g. the
+ * IPv4 and IPv6 modules share tcp_create_openreq_child, so if
+ * tcp_create_openreq_child called sk_set_owner IPv6 would have to
+ * change the ownership of this struct sock, with one not needed
+ * transient sk_set_owner call.
+ */
+ if (unlikely(sk->owner != NULL))
+ BUG();
+ sk->owner = owner;
+ __module_get(owner);
+}
+
/* Called with local bh disabled */
static __inline__ void sock_prot_inc_use(struct proto *prot)
{
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 1599f7a5667f..ae137e716769 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1778,6 +1778,7 @@ static struct net_proto_family atalk_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.family = PF_APPLETALK,
+ .owner = THIS_MODULE,
.release = atalk_release,
.bind = atalk_bind,
.connect = atalk_connect,
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index a37fa1c2d75d..e1cf71538c28 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -845,6 +845,7 @@ int ax25_create(struct socket *sock, int protocol)
}
sock_init_data(sock, sk);
+ sk_set_owner(sk, THIS_MODULE);
sk->destruct = ax25_free_sock;
sock->ops = &ax25_proto_ops;
@@ -880,6 +881,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
}
sock_init_data(NULL, sk);
+ sk_set_owner(sk, THIS_MODULE);
sk->destruct = ax25_free_sock;
sk->type = osk->type;
@@ -1913,7 +1915,7 @@ static struct net_proto_family ax25_family_ops = {
static struct proto_ops ax25_proto_ops = {
.family = PF_AX25,
-
+ .owner = THIS_MODULE,
.release = ax25_release,
.bind = ax25_bind,
.connect = ax25_connect,
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 91310913ca78..60d22f5e5820 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -148,6 +148,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
static struct proto_ops bnep_sock_ops = {
.family = PF_BLUETOOTH,
+ .owner = THIS_MODULE,
.release = bnep_sock_release,
.ioctl = bnep_sock_ioctl,
.bind = sock_no_bind,
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 952f6de9d8b5..61429363982c 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -553,6 +553,7 @@ int hci_sock_getsockopt(struct socket *sock, int level, int optname, char *optva
struct proto_ops hci_sock_ops = {
.family = PF_BLUETOOTH,
+ .owner = THIS_MODULE,
.release = hci_sock_release,
.bind = hci_sock_bind,
.getname = hci_sock_getname,
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index dff6a585c10a..fe811355a735 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2084,6 +2084,7 @@ static void __exit l2cap_proc_cleanup(void)
static struct proto_ops l2cap_sock_ops = {
.family = PF_BLUETOOTH,
+ .owner = THIS_MODULE,
.release = l2cap_sock_release,
.bind = l2cap_sock_bind,
.connect = l2cap_sock_connect,
@@ -2104,6 +2105,7 @@ static struct proto_ops l2cap_sock_ops = {
static struct net_proto_family l2cap_sock_family_ops = {
.family = PF_BLUETOOTH,
.create = l2cap_sock_create,
+ .owner = THIS_MODULE,
};
static struct hci_proto l2cap_hci_proto = {
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index c85e4e16bae1..81bdda3ce9bd 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -856,6 +856,7 @@ static void __exit rfcomm_sock_proc_cleanup(void)
static struct proto_ops rfcomm_sock_ops = {
.family = PF_BLUETOOTH,
+ .owner = THIS_MODULE,
.release = rfcomm_sock_release,
.bind = rfcomm_sock_bind,
.connect = rfcomm_sock_connect,
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index de427d58993e..02ac269362f1 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -969,6 +969,7 @@ static void __exit sco_proc_cleanup(void)
static struct proto_ops sco_sock_ops = {
.family = PF_BLUETOOTH,
+ .owner = THIS_MODULE,
.release = sco_sock_release,
.bind = sco_sock_bind,
.connect = sco_sock_connect,
@@ -989,6 +990,7 @@ static struct proto_ops sco_sock_ops = {
static struct net_proto_family sco_sock_family_ops = {
.family = PF_BLUETOOTH,
.create = sco_sock_create,
+ .owner = THIS_MODULE,
};
static struct hci_proto sco_hci_proto = {
diff --git a/net/core/sock.c b/net/core/sock.c
index 29fdc583abe3..82e8942061db 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -591,8 +591,6 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
{
struct sock *sk = NULL;
- if (!net_family_get(family))
- goto out;
if (!slab)
slab = sk_cachep;
sk = kmem_cache_alloc(slab, priority);
@@ -604,16 +602,14 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
sock_lock_init(sk);
}
sk->slab = slab;
- } else
- net_family_put(family);
-out:
+ }
return sk;
}
void sk_free(struct sock *sk)
{
struct sk_filter *filter;
- const int family = sk->family;
+ struct module *owner = sk->owner;
if (sk->destruct)
sk->destruct(sk);
@@ -628,7 +624,7 @@ void sk_free(struct sock *sk)
printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
kmem_cache_free(sk->slab, sk);
- net_family_put(family);
+ module_put(owner);
}
void __init sk_init(void)
@@ -1112,6 +1108,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
sk->rcvlowat = 1;
sk->rcvtimeo = MAX_SCHEDULE_TIMEOUT;
sk->sndtimeo = MAX_SCHEDULE_TIMEOUT;
+ sk->owner = NULL;
atomic_set(&sk->refcnt, 1);
}
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index d86cdd5636d2..4d6ed7ac8c56 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -485,6 +485,7 @@ struct sock *dn_alloc_sock(struct socket *sock, int gfp)
if (sock)
sock->ops = &dn_proto_ops;
sock_init_data(sock, sk);
+ sk_set_owner(sk, THIS_MODULE);
sk->backlog_rcv = dn_nsp_backlog_rcv;
sk->destruct = dn_destruct;
@@ -2235,7 +2236,7 @@ static struct net_proto_family dn_family_ops = {
static struct proto_ops dn_proto_ops = {
.family = AF_DECnet,
-
+ .owner = THIS_MODULE,
.release = dn_release,
.bind = dn_bind,
.connect = dn_connect,
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 02bc811383df..d032e1929007 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -694,7 +694,7 @@ static struct net_proto_family econet_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
.family = PF_ECONET,
-
+ .owner = THIS_MODULE,
.release = econet_release,
.bind = econet_bind,
.connect = sock_no_connect,
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 390c24c2a45b..eb97374a3d85 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -390,6 +390,7 @@ static int inet_create(struct socket *sock, int protocol)
inet->id = 0;
sock_init_data(sock, sk);
+ sk_set_owner(sk, THIS_MODULE);
sk->destruct = inet_sock_destruct;
sk->zapped = 0;
@@ -882,7 +883,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
struct proto_ops inet_stream_ops = {
.family = PF_INET,
-
+ .owner = THIS_MODULE,
.release = inet_release,
.bind = inet_bind,
.connect = inet_stream_connect,
@@ -903,7 +904,7 @@ struct proto_ops inet_stream_ops = {
struct proto_ops inet_dgram_ops = {
.family = PF_INET,
-
+ .owner = THIS_MODULE,
.release = inet_release,
.bind = inet_bind,
.connect = inet_dgram_connect,
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index ae6ac63877b3..2047c3d31c9b 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -101,9 +101,10 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
struct sock *child;
child = tp->af_specific->syn_recv_sock(sk, skb, req, dst);
- if (child)
+ if (child) {
+ sk_set_owner(child, sk->owner);
tcp_acceptq_queue(sk, req, child);
- else
+ } else
tcp_openreq_free(req);
return child;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index da1f688c06a4..1bf1edc09f64 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -967,6 +967,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
if (child == NULL)
goto listen_overflow;
+ sk_set_owner(child, sk->owner);
tcp_synq_unlink(tp, req, prev);
tcp_synq_removed(sk, req);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index ec9830912bc1..c2179b1c97c8 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -193,6 +193,7 @@ static int inet6_create(struct socket *sock, int protocol)
sock->ops = answer->ops;
sock_init_data(sock, sk);
+ sk_set_owner(sk, THIS_MODULE);
sk->prot = answer->prot;
sk->no_check = answer->no_check;
@@ -498,7 +499,7 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
struct proto_ops inet6_stream_ops = {
.family = PF_INET6,
-
+ .owner = THIS_MODULE,
.release = inet6_release,
.bind = inet6_bind,
.connect = inet_stream_connect, /* ok */
@@ -519,7 +520,7 @@ struct proto_ops inet6_stream_ops = {
struct proto_ops inet6_dgram_ops = {
.family = PF_INET6,
-
+ .owner = THIS_MODULE,
.release = inet6_release,
.bind = inet6_bind,
.connect = inet_dgram_connect, /* ok */
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index a04e68cb3e5f..d436c304b4c9 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1309,7 +1309,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
#ifdef INET_REFCNT_DEBUG
atomic_inc(&inet6_sock_nr);
#endif
- MOD_INC_USE_COUNT;
/* It is tricky place. Until this moment IPv4 tcp
worked with IPv6 af_tcp.af_specific.
@@ -1359,7 +1358,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
#ifdef INET_REFCNT_DEBUG
atomic_inc(&inet6_sock_nr);
#endif
- MOD_INC_USE_COUNT;
ip6_dst_store(newsk, dst, NULL);
sk->route_caps = dst->dev->features&~(NETIF_F_IP_CSUM|NETIF_F_TSO);
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index b64583b689e1..55ae155d4ae6 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -2221,6 +2221,7 @@ static struct net_proto_family ipx_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
.family = PF_IPX,
+ .owner = THIS_MODULE,
.release = ipx_release,
.bind = ipx_bind,
.connect = ipx_connect,
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 28975474e5d2..90077d0f1168 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -2408,7 +2408,7 @@ static struct net_proto_family irda_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.family = PF_IRDA,
-
+ .owner = THIS_MODULE,
.release = irda_release,
.bind = irda_bind,
.connect = irda_connect,
@@ -2429,7 +2429,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.family = PF_IRDA,
-
+ .owner = THIS_MODULE,
.release = irda_release,
.bind = irda_bind,
.connect = irda_connect,
@@ -2450,7 +2450,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.family = PF_IRDA,
-
+ .owner = THIS_MODULE,
.release = irda_release,
.bind = irda_bind,
.connect = irda_connect,
@@ -2472,7 +2472,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
#ifdef CONFIG_IRDA_ULTRA
static struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.family = PF_IRDA,
-
+ .owner = THIS_MODULE,
.release = irda_release,
.bind = irda_bind,
.connect = sock_no_connect,
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 3292da01510f..b91167dd30e4 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -152,9 +152,10 @@ static int pfkey_create(struct socket *sock, int protocol)
sk = sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL);
if (sk == NULL)
goto out;
-
+
sock->ops = &pfkey_ops;
sock_init_data(sock, sk);
+ sk_set_owner(sk, THIS_MODULE);
err = -ENOMEM;
pfk = pfkey_sk(sk) = kmalloc(sizeof(*pfk), GFP_KERNEL);
@@ -2761,7 +2762,7 @@ out:
static struct proto_ops pfkey_ops = {
.family = PF_KEY,
-
+ .owner = THIS_MODULE,
/* Operations that make no sense on pfkey sockets. */
.bind = sock_no_bind,
.connect = sock_no_connect,
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 776b4378c75f..c50d55b4765b 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -1023,6 +1023,7 @@ static struct net_proto_family llc_ui_family_ops = {
static struct proto_ops llc_ui_ops = {
.family = PF_LLC,
+ .owner = THIS_MODULE,
.release = llc_ui_release,
.bind = llc_ui_bind,
.connect = llc_ui_connect,
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index e972bef42859..27e47ed4ba6d 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -235,6 +235,7 @@ static int netlink_create(struct socket *sock, int protocol)
return -ENOMEM;
sock_init_data(sock,sk);
+ sk_set_owner(sk, THIS_MODULE);
nlk = nlk_sk(sk) = kmalloc(sizeof(*nlk), GFP_KERNEL);
if (!nlk) {
@@ -1030,7 +1031,7 @@ int netlink_unregister_notifier(struct notifier_block *nb)
struct proto_ops netlink_ops = {
.family = PF_NETLINK,
-
+ .owner = THIS_MODULE,
.release = netlink_release,
.bind = netlink_bind,
.connect = netlink_connect,
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 62545cbe1a67..a3d9a6d24dab 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1227,7 +1227,7 @@ static struct net_proto_family nr_family_ops = {
static struct proto_ops nr_proto_ops = {
.family = PF_NETROM,
-
+ .owner = THIS_MODULE,
.release = nr_release,
.bind = nr_bind,
.connect = nr_connect,
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index a0b8acb049df..4e5c32189076 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -950,6 +950,7 @@ static int packet_create(struct socket *sock, int protocol)
sock->ops = &packet_ops_spkt;
#endif
sock_init_data(sock,sk);
+ sk_set_owner(sk, THIS_MODULE);
po = pkt_sk(sk) = kmalloc(sizeof(*po), GFP_KERNEL);
if (!po)
@@ -1705,7 +1706,7 @@ out:
#ifdef CONFIG_SOCK_PACKET
struct proto_ops packet_ops_spkt = {
.family = PF_PACKET,
-
+ .owner = THIS_MODULE,
.release = packet_release,
.bind = packet_bind_spkt,
.connect = sock_no_connect,
@@ -1727,7 +1728,7 @@ struct proto_ops packet_ops_spkt = {
struct proto_ops packet_ops = {
.family = PF_PACKET,
-
+ .owner = THIS_MODULE,
.release = packet_release,
.bind = packet_bind,
.connect = sock_no_connect,
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index a5071a5eb5bd..e1abedac823f 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1424,7 +1424,7 @@ static struct net_proto_family rose_family_ops = {
static struct proto_ops rose_proto_ops = {
.family = PF_ROSE,
-
+ .owner = THIS_MODULE,
.release = rose_release,
.bind = rose_bind,
.connect = rose_connect,
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 80e5171f3053..37fadd010664 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -508,6 +508,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
goto out;
sock_init_data(NULL, newsk);
+ sk_set_owner(newsk, THIS_MODULE);
newsk->type = SOCK_STREAM;
@@ -749,6 +750,7 @@ static int sctp_inet6_supported_addrs(const struct sctp_opt *opt,
static struct proto_ops inet6_seqpacket_ops = {
.family = PF_INET6,
+ .owner = THIS_MODULE,
.release = inet6_release,
.bind = inet6_bind,
.connect = inet_dgram_connect,
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index a9a271fc47c4..f6ac1373b821 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -499,6 +499,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
goto out;
sock_init_data(NULL, newsk);
+ sk_set_owner(newsk, THIS_MODULE);
newsk->type = SOCK_STREAM;
@@ -748,6 +749,7 @@ struct notifier_block sctp_inetaddr_notifier = {
/* Socket operations. */
struct proto_ops inet_seqpacket_ops = {
.family = PF_INET,
+ .owner = THIS_MODULE,
.release = inet_release, /* Needs to be wrapped... */
.bind = inet_bind,
.connect = inet_dgram_connect,
diff --git a/net/socket.c b/net/socket.c
index d95971cd3333..9e49a7bd82f1 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -141,36 +141,6 @@ static struct file_operations socket_file_ops = {
static struct net_proto_family *net_families[NPROTO];
-static __inline__ void net_family_bug(int family)
-{
- printk(KERN_ERR "%d is not yet sock_registered!\n", family);
- BUG();
-}
-
-int net_family_get(int family)
-{
- struct net_proto_family *prot = net_families[family];
- int rc = 1;
-
- barrier();
- if (likely(prot != NULL))
- rc = try_module_get(prot->owner);
- else
- net_family_bug(family);
- return rc;
-}
-
-void net_family_put(int family)
-{
- struct net_proto_family *prot = net_families[family];
-
- barrier();
- if (likely(prot != NULL))
- module_put(prot->owner);
- else
- net_family_bug(family);
-}
-
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static atomic_t net_family_lockct = ATOMIC_INIT(0);
static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED;
@@ -535,11 +505,11 @@ struct file_operations bad_sock_fops = {
void sock_release(struct socket *sock)
{
if (sock->ops) {
- const int family = sock->ops->family;
+ struct module *owner = sock->ops->owner;
sock->ops->release(sock);
sock->ops = NULL;
- net_family_put(family);
+ module_put(owner);
}
if (sock->fasync_list)
@@ -1091,19 +1061,37 @@ int sock_create(int family, int type, int protocol, struct socket **res)
sock->type = type;
+ /*
+ * We will call the ->create function, that possibly is in a loadable
+ * module, so we have to bump that loadable module refcnt first.
+ */
i = -EAFNOSUPPORT;
- if (!net_family_get(family))
- goto out_release;
-
- if ((i = net_families[family]->create(sock, protocol)) < 0)
+ if (!try_module_get(net_families[family]->owner))
goto out_release;
+ if ((i = net_families[family]->create(sock, protocol)) < 0)
+ goto out_module_put;
+ /*
+ * Now to bump the refcnt of the [loadable] module that owns this
+ * socket at sock_release time we decrement its refcnt.
+ */
+ if (!try_module_get(sock->ops->owner)) {
+ sock->ops = NULL;
+ goto out_module_put;
+ }
+ /*
+ * Now that we're done with the ->create function, the [loadable]
+ * module can have its refcnt decremented
+ */
+ module_put(net_families[family]->owner);
*res = sock;
security_socket_post_create(sock, family, type, protocol);
out:
net_family_read_unlock();
return i;
+out_module_put:
+ module_put(net_families[family]->owner);
out_release:
sock_release(sock);
goto out;
@@ -1288,28 +1276,30 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
if (err)
goto out_release;
- err = -EAFNOSUPPORT;
- if (!net_family_get(sock->ops->family))
- goto out_release;
+ /*
+ * We don't need try_module_get here, as the listening socket (sock)
+ * has the protocol module (sock->ops->owner) held.
+ */
+ __module_get(sock->ops->owner);
err = sock->ops->accept(sock, newsock, sock->file->f_flags);
if (err < 0)
- goto out_family_put;
+ goto out_module_put;
if (upeer_sockaddr) {
if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
err = -ECONNABORTED;
- goto out_family_put;
+ goto out_module_put;
}
err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
if (err < 0)
- goto out_family_put;
+ goto out_module_put;
}
/* File flags are not inherited via accept() unlike another OSes. */
if ((err = sock_map_fd(newsock)) < 0)
- goto out_family_put;
+ goto out_module_put;
security_socket_post_accept(sock, newsock);
@@ -1317,8 +1307,8 @@ out_put:
sockfd_put(sock);
out:
return err;
-out_family_put:
- net_family_put(sock->ops->family);
+out_module_put:
+ module_put(sock->ops->owner);
out_release:
sock_release(newsock);
goto out_put;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 0ba6e24475f9..0955346cc477 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -494,6 +494,7 @@ static struct sock * unix_create1(struct socket *sock)
atomic_inc(&unix_nr_socks);
sock_init_data(sock,sk);
+ sk_set_owner(sk, THIS_MODULE);
sk->write_space = unix_write_space;
@@ -1884,7 +1885,7 @@ done:
struct proto_ops unix_stream_ops = {
.family = PF_UNIX,
-
+ .owner = THIS_MODULE,
.release = unix_release,
.bind = unix_bind,
.connect = unix_stream_connect,
@@ -1905,7 +1906,7 @@ struct proto_ops unix_stream_ops = {
struct proto_ops unix_dgram_ops = {
.family = PF_UNIX,
-
+ .owner = THIS_MODULE,
.release = unix_release,
.bind = unix_bind,
.connect = unix_dgram_connect,
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 6e9f627d8b8f..c86ddd6add83 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -2551,7 +2551,7 @@ static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr
struct proto_ops wanpipe_ops = {
.family = PF_WANPIPE,
-
+ .owner = THIS_MODULE,
.release = wanpipe_release,
.bind = wanpipe_bind,
.connect = wanpipe_connect,
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 2330516d5eda..f4807d92e58e 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -1323,7 +1323,7 @@ struct net_proto_family x25_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.family = AF_X25,
-
+ .owner = THIS_MODULE,
.release = x25_release,
.bind = x25_bind,
.connect = x25_connect,