diff options
| author | David S. Miller <davem@nuts.ninka.net> | 2003-05-02 11:13:39 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2003-05-02 11:13:39 -0700 |
| commit | 8bbb2b4199fad5ac700564f4fff59c38d78fa808 (patch) | |
| tree | fb8bf30642a52ec1a428d7e119619fdd23621dc2 | |
| parent | d7920faf65a0950ca18e75e4980ce967dab5b36e (diff) | |
| parent | 8b97999a03d5b79c190be3b33859fa1d4bdab22d (diff) | |
Merge bk://kernel.bkbits.net/acme/net_family-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
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, |
