Commit 8bbb2b41 authored by David S. Miller's avatar David S. Miller

Merge bk://kernel.bkbits.net/acme/net_family-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents d7920faf 8b97999a
...@@ -494,16 +494,21 @@ static int pppoe_create(struct socket *sock) ...@@ -494,16 +494,21 @@ static int pppoe_create(struct socket *sock)
struct sock *sk; struct sock *sk;
struct pppox_opt *po; 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) if (!sk)
goto out; goto out;
sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
sock->ops = &pppoe_ops; sock->ops = &pppoe_ops;
sk->backlog_rcv = pppoe_rcv_core; sk->backlog_rcv = pppoe_rcv_core;
sk->state = PPPOX_NONE; sk->state = PPPOX_NONE;
sk->type = SOCK_STREAM; 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); po = pppox_sk(sk) = kmalloc(sizeof(*po), GFP_KERNEL);
if (!po) if (!po)
...@@ -1062,10 +1067,12 @@ static struct file_operations pppoe_seq_fops = { ...@@ -1062,10 +1067,12 @@ static struct file_operations pppoe_seq_fops = {
}; };
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
/* ->release and ->ioctl are set at pppox_create */ /* ->ioctl are set at pppox_create */
struct proto_ops pppoe_ops = { struct proto_ops pppoe_ops = {
.family = AF_PPPOX, .family = AF_PPPOX,
.owner = THIS_MODULE,
.release = pppoe_release,
.bind = sock_no_bind, .bind = sock_no_bind,
.connect = pppoe_connect, .connect = pppoe_connect,
.socketpair = sock_no_socketpair, .socketpair = sock_no_socketpair,
...@@ -1084,8 +1091,6 @@ struct proto_ops pppoe_ops = { ...@@ -1084,8 +1091,6 @@ struct proto_ops pppoe_ops = {
struct pppox_proto pppoe_proto = { struct pppox_proto pppoe_proto = {
.create = pppoe_create, .create = pppoe_create,
.ioctl = pppoe_ioctl, .ioctl = pppoe_ioctl,
.release = pppoe_release,
.sk_free = pppoe_sk_free,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -64,45 +64,9 @@ void pppox_unbind_sock(struct sock *sk) ...@@ -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(register_pppox_proto);
EXPORT_SYMBOL(unregister_pppox_proto); EXPORT_SYMBOL(unregister_pppox_proto);
EXPORT_SYMBOL(pppox_unbind_sock); EXPORT_SYMBOL(pppox_unbind_sock);
EXPORT_SYMBOL(pppox_sk_alloc);
static int pppox_ioctl(struct socket* sock, unsigned int cmd, static int pppox_ioctl(struct socket* sock, unsigned int cmd,
unsigned long arg) unsigned long arg)
...@@ -156,12 +120,10 @@ static int pppox_create(struct socket *sock, int protocol) ...@@ -156,12 +120,10 @@ static int pppox_create(struct socket *sock, int protocol)
rc = pppox_protos[protocol]->create(sock); rc = pppox_protos[protocol]->create(sock);
if (!rc) { if (!rc) {
/* We get to set the ioctl handler. */ /* We get to set the ioctl handler. */
/* And the release handler, for module refcounting */
/* For everything else, pppox is just a shell. */ /* For everything else, pppox is just a shell. */
sock->ops->ioctl = pppox_ioctl; sock->ops->ioctl = pppox_ioctl;
sock->ops->release = pppox_release; }
} else module_put(pppox_protos[protocol]->owner);
module_put(pppox_protos[protocol]->owner);
out: out:
return rc; return rc;
} }
......
...@@ -140,8 +140,6 @@ struct pppox_proto { ...@@ -140,8 +140,6 @@ struct pppox_proto {
int (*create)(struct socket *sock); int (*create)(struct socket *sock);
int (*ioctl)(struct socket *sock, unsigned int cmd, int (*ioctl)(struct socket *sock, unsigned int cmd,
unsigned long arg); unsigned long arg);
int (*release)(struct socket *sock);
void (*sk_free)(struct sock *sk);
struct module *owner; struct module *owner;
}; };
...@@ -150,9 +148,6 @@ extern void unregister_pppox_proto(int proto_num); ...@@ -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 void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
extern int pppox_channel_ioctl(struct ppp_channel *pc, unsigned int cmd, extern int pppox_channel_ioctl(struct ppp_channel *pc, unsigned int cmd,
unsigned long arg); 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 */ /* PPPoX socket states */
enum { enum {
......
...@@ -89,9 +89,11 @@ struct page; ...@@ -89,9 +89,11 @@ struct page;
struct kiocb; struct kiocb;
struct sockaddr; struct sockaddr;
struct msghdr; struct msghdr;
struct module;
struct proto_ops { struct proto_ops {
int family; int family;
struct module *owner;
int (*release) (struct socket *sock); int (*release) (struct socket *sock);
int (*bind) (struct socket *sock, int (*bind) (struct socket *sock,
struct sockaddr *umyaddr, struct sockaddr *umyaddr,
...@@ -127,8 +129,6 @@ struct proto_ops { ...@@ -127,8 +129,6 @@ struct proto_ops {
int offset, size_t size, int flags); int offset, size_t size, int flags);
}; };
struct module;
struct net_proto_family { struct net_proto_family {
int family; int family;
int (*create)(struct socket *sock, int protocol); int (*create)(struct socket *sock, int protocol);
...@@ -140,9 +140,6 @@ struct net_proto_family { ...@@ -140,9 +140,6 @@ struct net_proto_family {
struct module *owner; struct module *owner;
}; };
extern int net_family_get(int family);
extern void net_family_put(int family);
struct iovec; struct iovec;
extern int sock_wake_async(struct socket *sk, int how, int band); 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 ...@@ -227,7 +224,7 @@ SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_are
\ \
static struct proto_ops name##_ops = { \ static struct proto_ops name##_ops = { \
.family = fam, \ .family = fam, \
\ .owner = THIS_MODULE, \
.release = __lock_##name##_release, \ .release = __lock_##name##_release, \
.bind = __lock_##name##_bind, \ .bind = __lock_##name##_bind, \
.connect = __lock_##name##_connect, \ .connect = __lock_##name##_connect, \
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/module.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/skbuff.h> /* struct sk_buff */ #include <linux/skbuff.h> /* struct sk_buff */
#include <linux/security.h> #include <linux/security.h>
...@@ -197,6 +197,7 @@ struct sock { ...@@ -197,6 +197,7 @@ struct sock {
void *user_data; void *user_data;
/* Callbacks */ /* Callbacks */
struct module *owner;
void (*state_change)(struct sock *sk); void (*state_change)(struct sock *sk);
void (*data_ready)(struct sock *sk,int bytes); void (*data_ready)(struct sock *sk,int bytes);
void (*write_space)(struct sock *sk); void (*write_space)(struct sock *sk);
...@@ -270,6 +271,23 @@ struct proto { ...@@ -270,6 +271,23 @@ struct proto {
} stats[NR_CPUS]; } 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 */ /* Called with local bh disabled */
static __inline__ void sock_prot_inc_use(struct proto *prot) static __inline__ void sock_prot_inc_use(struct proto *prot)
{ {
......
...@@ -1778,6 +1778,7 @@ static struct net_proto_family atalk_family_ops = { ...@@ -1778,6 +1778,7 @@ static struct net_proto_family atalk_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.family = PF_APPLETALK, .family = PF_APPLETALK,
.owner = THIS_MODULE,
.release = atalk_release, .release = atalk_release,
.bind = atalk_bind, .bind = atalk_bind,
.connect = atalk_connect, .connect = atalk_connect,
......
...@@ -845,6 +845,7 @@ int ax25_create(struct socket *sock, int protocol) ...@@ -845,6 +845,7 @@ int ax25_create(struct socket *sock, int protocol)
} }
sock_init_data(sock, sk); sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
sk->destruct = ax25_free_sock; sk->destruct = ax25_free_sock;
sock->ops = &ax25_proto_ops; sock->ops = &ax25_proto_ops;
...@@ -880,6 +881,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev) ...@@ -880,6 +881,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
} }
sock_init_data(NULL, sk); sock_init_data(NULL, sk);
sk_set_owner(sk, THIS_MODULE);
sk->destruct = ax25_free_sock; sk->destruct = ax25_free_sock;
sk->type = osk->type; sk->type = osk->type;
...@@ -1913,7 +1915,7 @@ static struct net_proto_family ax25_family_ops = { ...@@ -1913,7 +1915,7 @@ static struct net_proto_family ax25_family_ops = {
static struct proto_ops ax25_proto_ops = { static struct proto_ops ax25_proto_ops = {
.family = PF_AX25, .family = PF_AX25,
.owner = THIS_MODULE,
.release = ax25_release, .release = ax25_release,
.bind = ax25_bind, .bind = ax25_bind,
.connect = ax25_connect, .connect = ax25_connect,
......
...@@ -148,6 +148,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long ...@@ -148,6 +148,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
static struct proto_ops bnep_sock_ops = { static struct proto_ops bnep_sock_ops = {
.family = PF_BLUETOOTH, .family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = bnep_sock_release, .release = bnep_sock_release,
.ioctl = bnep_sock_ioctl, .ioctl = bnep_sock_ioctl,
.bind = sock_no_bind, .bind = sock_no_bind,
......
...@@ -553,6 +553,7 @@ int hci_sock_getsockopt(struct socket *sock, int level, int optname, char *optva ...@@ -553,6 +553,7 @@ int hci_sock_getsockopt(struct socket *sock, int level, int optname, char *optva
struct proto_ops hci_sock_ops = { struct proto_ops hci_sock_ops = {
.family = PF_BLUETOOTH, .family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = hci_sock_release, .release = hci_sock_release,
.bind = hci_sock_bind, .bind = hci_sock_bind,
.getname = hci_sock_getname, .getname = hci_sock_getname,
......
...@@ -2084,6 +2084,7 @@ static void __exit l2cap_proc_cleanup(void) ...@@ -2084,6 +2084,7 @@ static void __exit l2cap_proc_cleanup(void)
static struct proto_ops l2cap_sock_ops = { static struct proto_ops l2cap_sock_ops = {
.family = PF_BLUETOOTH, .family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = l2cap_sock_release, .release = l2cap_sock_release,
.bind = l2cap_sock_bind, .bind = l2cap_sock_bind,
.connect = l2cap_sock_connect, .connect = l2cap_sock_connect,
...@@ -2104,6 +2105,7 @@ static struct proto_ops l2cap_sock_ops = { ...@@ -2104,6 +2105,7 @@ static struct proto_ops l2cap_sock_ops = {
static struct net_proto_family l2cap_sock_family_ops = { static struct net_proto_family l2cap_sock_family_ops = {
.family = PF_BLUETOOTH, .family = PF_BLUETOOTH,
.create = l2cap_sock_create, .create = l2cap_sock_create,
.owner = THIS_MODULE,
}; };
static struct hci_proto l2cap_hci_proto = { static struct hci_proto l2cap_hci_proto = {
......
...@@ -856,6 +856,7 @@ static void __exit rfcomm_sock_proc_cleanup(void) ...@@ -856,6 +856,7 @@ static void __exit rfcomm_sock_proc_cleanup(void)
static struct proto_ops rfcomm_sock_ops = { static struct proto_ops rfcomm_sock_ops = {
.family = PF_BLUETOOTH, .family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = rfcomm_sock_release, .release = rfcomm_sock_release,
.bind = rfcomm_sock_bind, .bind = rfcomm_sock_bind,
.connect = rfcomm_sock_connect, .connect = rfcomm_sock_connect,
......
...@@ -969,6 +969,7 @@ static void __exit sco_proc_cleanup(void) ...@@ -969,6 +969,7 @@ static void __exit sco_proc_cleanup(void)
static struct proto_ops sco_sock_ops = { static struct proto_ops sco_sock_ops = {
.family = PF_BLUETOOTH, .family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = sco_sock_release, .release = sco_sock_release,
.bind = sco_sock_bind, .bind = sco_sock_bind,
.connect = sco_sock_connect, .connect = sco_sock_connect,
...@@ -989,6 +990,7 @@ static struct proto_ops sco_sock_ops = { ...@@ -989,6 +990,7 @@ static struct proto_ops sco_sock_ops = {
static struct net_proto_family sco_sock_family_ops = { static struct net_proto_family sco_sock_family_ops = {
.family = PF_BLUETOOTH, .family = PF_BLUETOOTH,
.create = sco_sock_create, .create = sco_sock_create,
.owner = THIS_MODULE,
}; };
static struct hci_proto sco_hci_proto = { static struct hci_proto sco_hci_proto = {
......
...@@ -591,8 +591,6 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab) ...@@ -591,8 +591,6 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
{ {
struct sock *sk = NULL; struct sock *sk = NULL;
if (!net_family_get(family))
goto out;
if (!slab) if (!slab)
slab = sk_cachep; slab = sk_cachep;
sk = kmem_cache_alloc(slab, priority); 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) ...@@ -604,16 +602,14 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
sock_lock_init(sk); sock_lock_init(sk);
} }
sk->slab = slab; sk->slab = slab;
} else }
net_family_put(family);
out:
return sk; return sk;
} }
void sk_free(struct sock *sk) void sk_free(struct sock *sk)
{ {
struct sk_filter *filter; struct sk_filter *filter;
const int family = sk->family; struct module *owner = sk->owner;
if (sk->destruct) if (sk->destruct)
sk->destruct(sk); sk->destruct(sk);
...@@ -628,7 +624,7 @@ void sk_free(struct sock *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)); printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
kmem_cache_free(sk->slab, sk); kmem_cache_free(sk->slab, sk);
net_family_put(family); module_put(owner);
} }
void __init sk_init(void) void __init sk_init(void)
...@@ -1112,6 +1108,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) ...@@ -1112,6 +1108,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
sk->rcvlowat = 1; sk->rcvlowat = 1;
sk->rcvtimeo = MAX_SCHEDULE_TIMEOUT; sk->rcvtimeo = MAX_SCHEDULE_TIMEOUT;
sk->sndtimeo = MAX_SCHEDULE_TIMEOUT; sk->sndtimeo = MAX_SCHEDULE_TIMEOUT;
sk->owner = NULL;
atomic_set(&sk->refcnt, 1); atomic_set(&sk->refcnt, 1);
} }
...@@ -485,6 +485,7 @@ struct sock *dn_alloc_sock(struct socket *sock, int gfp) ...@@ -485,6 +485,7 @@ struct sock *dn_alloc_sock(struct socket *sock, int gfp)
if (sock) if (sock)
sock->ops = &dn_proto_ops; sock->ops = &dn_proto_ops;
sock_init_data(sock, sk); sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
sk->backlog_rcv = dn_nsp_backlog_rcv; sk->backlog_rcv = dn_nsp_backlog_rcv;
sk->destruct = dn_destruct; sk->destruct = dn_destruct;
...@@ -2235,7 +2236,7 @@ static struct net_proto_family dn_family_ops = { ...@@ -2235,7 +2236,7 @@ static struct net_proto_family dn_family_ops = {
static struct proto_ops dn_proto_ops = { static struct proto_ops dn_proto_ops = {
.family = AF_DECnet, .family = AF_DECnet,
.owner = THIS_MODULE,
.release = dn_release, .release = dn_release,
.bind = dn_bind, .bind = dn_bind,
.connect = dn_connect, .connect = dn_connect,
......
...@@ -694,7 +694,7 @@ static struct net_proto_family econet_family_ops = { ...@@ -694,7 +694,7 @@ static struct net_proto_family econet_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
.family = PF_ECONET, .family = PF_ECONET,
.owner = THIS_MODULE,
.release = econet_release, .release = econet_release,
.bind = econet_bind, .bind = econet_bind,
.connect = sock_no_connect, .connect = sock_no_connect,
......
...@@ -390,6 +390,7 @@ static int inet_create(struct socket *sock, int protocol) ...@@ -390,6 +390,7 @@ static int inet_create(struct socket *sock, int protocol)
inet->id = 0; inet->id = 0;
sock_init_data(sock, sk); sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
sk->destruct = inet_sock_destruct; sk->destruct = inet_sock_destruct;
sk->zapped = 0; sk->zapped = 0;
...@@ -882,7 +883,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -882,7 +883,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
struct proto_ops inet_stream_ops = { struct proto_ops inet_stream_ops = {
.family = PF_INET, .family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release, .release = inet_release,
.bind = inet_bind, .bind = inet_bind,
.connect = inet_stream_connect, .connect = inet_stream_connect,
...@@ -903,7 +904,7 @@ struct proto_ops inet_stream_ops = { ...@@ -903,7 +904,7 @@ struct proto_ops inet_stream_ops = {
struct proto_ops inet_dgram_ops = { struct proto_ops inet_dgram_ops = {
.family = PF_INET, .family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release, .release = inet_release,
.bind = inet_bind, .bind = inet_bind,
.connect = inet_dgram_connect, .connect = inet_dgram_connect,
......
...@@ -101,9 +101,10 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, ...@@ -101,9 +101,10 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
struct sock *child; struct sock *child;
child = tp->af_specific->syn_recv_sock(sk, skb, req, dst); 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); tcp_acceptq_queue(sk, req, child);
else } else
tcp_openreq_free(req); tcp_openreq_free(req);
return child; return child;
......
...@@ -967,6 +967,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, ...@@ -967,6 +967,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
if (child == NULL) if (child == NULL)
goto listen_overflow; goto listen_overflow;
sk_set_owner(child, sk->owner);
tcp_synq_unlink(tp, req, prev); tcp_synq_unlink(tp, req, prev);
tcp_synq_removed(sk, req); tcp_synq_removed(sk, req);
......
...@@ -193,6 +193,7 @@ static int inet6_create(struct socket *sock, int protocol) ...@@ -193,6 +193,7 @@ static int inet6_create(struct socket *sock, int protocol)
sock->ops = answer->ops; sock->ops = answer->ops;
sock_init_data(sock, sk); sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
sk->prot = answer->prot; sk->prot = answer->prot;
sk->no_check = answer->no_check; sk->no_check = answer->no_check;
...@@ -498,7 +499,7 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -498,7 +499,7 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
struct proto_ops inet6_stream_ops = { struct proto_ops inet6_stream_ops = {
.family = PF_INET6, .family = PF_INET6,
.owner = THIS_MODULE,
.release = inet6_release, .release = inet6_release,
.bind = inet6_bind, .bind = inet6_bind,
.connect = inet_stream_connect, /* ok */ .connect = inet_stream_connect, /* ok */
...@@ -519,7 +520,7 @@ struct proto_ops inet6_stream_ops = { ...@@ -519,7 +520,7 @@ struct proto_ops inet6_stream_ops = {
struct proto_ops inet6_dgram_ops = { struct proto_ops inet6_dgram_ops = {
.family = PF_INET6, .family = PF_INET6,
.owner = THIS_MODULE,
.release = inet6_release, .release = inet6_release,
.bind = inet6_bind, .bind = inet6_bind,
.connect = inet_dgram_connect, /* ok */ .connect = inet_dgram_connect, /* ok */
......
...@@ -1309,7 +1309,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, ...@@ -1309,7 +1309,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
#ifdef INET_REFCNT_DEBUG #ifdef INET_REFCNT_DEBUG
atomic_inc(&inet6_sock_nr); atomic_inc(&inet6_sock_nr);
#endif #endif
MOD_INC_USE_COUNT;
/* It is tricky place. Until this moment IPv4 tcp /* It is tricky place. Until this moment IPv4 tcp
worked with IPv6 af_tcp.af_specific. 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, ...@@ -1359,7 +1358,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
#ifdef INET_REFCNT_DEBUG #ifdef INET_REFCNT_DEBUG
atomic_inc(&inet6_sock_nr); atomic_inc(&inet6_sock_nr);
#endif #endif
MOD_INC_USE_COUNT;
ip6_dst_store(newsk, dst, NULL); ip6_dst_store(newsk, dst, NULL);
sk->route_caps = dst->dev->features&~(NETIF_F_IP_CSUM|NETIF_F_TSO); sk->route_caps = dst->dev->features&~(NETIF_F_IP_CSUM|NETIF_F_TSO);
......
...@@ -2221,6 +2221,7 @@ static struct net_proto_family ipx_family_ops = { ...@@ -2221,6 +2221,7 @@ static struct net_proto_family ipx_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
.family = PF_IPX, .family = PF_IPX,
.owner = THIS_MODULE,
.release = ipx_release, .release = ipx_release,
.bind = ipx_bind, .bind = ipx_bind,
.connect = ipx_connect, .connect = ipx_connect,
......
...@@ -2408,7 +2408,7 @@ static struct net_proto_family irda_family_ops = { ...@@ -2408,7 +2408,7 @@ static struct net_proto_family irda_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.family = PF_IRDA, .family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release, .release = irda_release,
.bind = irda_bind, .bind = irda_bind,
.connect = irda_connect, .connect = irda_connect,
...@@ -2429,7 +2429,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { ...@@ -2429,7 +2429,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.family = PF_IRDA, .family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release, .release = irda_release,
.bind = irda_bind, .bind = irda_bind,
.connect = irda_connect, .connect = irda_connect,
...@@ -2450,7 +2450,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { ...@@ -2450,7 +2450,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.family = PF_IRDA, .family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release, .release = irda_release,
.bind = irda_bind, .bind = irda_bind,
.connect = irda_connect, .connect = irda_connect,
...@@ -2472,7 +2472,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { ...@@ -2472,7 +2472,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
#ifdef CONFIG_IRDA_ULTRA #ifdef CONFIG_IRDA_ULTRA
static struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { static struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.family = PF_IRDA, .family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release, .release = irda_release,
.bind = irda_bind, .bind = irda_bind,
.connect = sock_no_connect, .connect = sock_no_connect,
......
...@@ -152,9 +152,10 @@ static int pfkey_create(struct socket *sock, int protocol) ...@@ -152,9 +152,10 @@ static int pfkey_create(struct socket *sock, int protocol)
sk = sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL); sk = sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL);
if (sk == NULL) if (sk == NULL)
goto out; goto out;
sock->ops = &pfkey_ops; sock->ops = &pfkey_ops;
sock_init_data(sock, sk); sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
err = -ENOMEM; err = -ENOMEM;
pfk = pfkey_sk(sk) = kmalloc(sizeof(*pfk), GFP_KERNEL); pfk = pfkey_sk(sk) = kmalloc(sizeof(*pfk), GFP_KERNEL);
...@@ -2761,7 +2762,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb, ...@@ -2761,7 +2762,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
static struct proto_ops pfkey_ops = { static struct proto_ops pfkey_ops = {
.family = PF_KEY, .family = PF_KEY,
.owner = THIS_MODULE,
/* Operations that make no sense on pfkey sockets. */ /* Operations that make no sense on pfkey sockets. */
.bind = sock_no_bind, .bind = sock_no_bind,
.connect = sock_no_connect, .connect = sock_no_connect,
......
...@@ -1023,6 +1023,7 @@ static struct net_proto_family llc_ui_family_ops = { ...@@ -1023,6 +1023,7 @@ static struct net_proto_family llc_ui_family_ops = {
static struct proto_ops llc_ui_ops = { static struct proto_ops llc_ui_ops = {
.family = PF_LLC, .family = PF_LLC,
.owner = THIS_MODULE,
.release = llc_ui_release, .release = llc_ui_release,
.bind = llc_ui_bind, .bind = llc_ui_bind,
.connect = llc_ui_connect, .connect = llc_ui_connect,
......
...@@ -235,6 +235,7 @@ static int netlink_create(struct socket *sock, int protocol) ...@@ -235,6 +235,7 @@ static int netlink_create(struct socket *sock, int protocol)
return -ENOMEM; return -ENOMEM;
sock_init_data(sock,sk); sock_init_data(sock,sk);
sk_set_owner(sk, THIS_MODULE);
nlk = nlk_sk(sk) = kmalloc(sizeof(*nlk), GFP_KERNEL); nlk = nlk_sk(sk) = kmalloc(sizeof(*nlk), GFP_KERNEL);
if (!nlk) { if (!nlk) {
...@@ -1030,7 +1031,7 @@ int netlink_unregister_notifier(struct notifier_block *nb) ...@@ -1030,7 +1031,7 @@ int netlink_unregister_notifier(struct notifier_block *nb)
struct proto_ops netlink_ops = { struct proto_ops netlink_ops = {
.family = PF_NETLINK, .family = PF_NETLINK,
.owner = THIS_MODULE,
.release = netlink_release, .release = netlink_release,
.bind = netlink_bind, .bind = netlink_bind,
.connect = netlink_connect, .connect = netlink_connect,
......
...@@ -1227,7 +1227,7 @@ static struct net_proto_family nr_family_ops = { ...@@ -1227,7 +1227,7 @@ static struct net_proto_family nr_family_ops = {
static struct proto_ops nr_proto_ops = { static struct proto_ops nr_proto_ops = {
.family = PF_NETROM, .family = PF_NETROM,
.owner = THIS_MODULE,
.release = nr_release, .release = nr_release,
.bind = nr_bind, .bind = nr_bind,
.connect = nr_connect, .connect = nr_connect,
......
...@@ -950,6 +950,7 @@ static int packet_create(struct socket *sock, int protocol) ...@@ -950,6 +950,7 @@ static int packet_create(struct socket *sock, int protocol)
sock->ops = &packet_ops_spkt; sock->ops = &packet_ops_spkt;
#endif #endif
sock_init_data(sock,sk); sock_init_data(sock,sk);
sk_set_owner(sk, THIS_MODULE);
po = pkt_sk(sk) = kmalloc(sizeof(*po), GFP_KERNEL); po = pkt_sk(sk) = kmalloc(sizeof(*po), GFP_KERNEL);
if (!po) if (!po)
...@@ -1705,7 +1706,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st ...@@ -1705,7 +1706,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st
#ifdef CONFIG_SOCK_PACKET #ifdef CONFIG_SOCK_PACKET
struct proto_ops packet_ops_spkt = { struct proto_ops packet_ops_spkt = {
.family = PF_PACKET, .family = PF_PACKET,
.owner = THIS_MODULE,
.release = packet_release, .release = packet_release,
.bind = packet_bind_spkt, .bind = packet_bind_spkt,
.connect = sock_no_connect, .connect = sock_no_connect,
...@@ -1727,7 +1728,7 @@ struct proto_ops packet_ops_spkt = { ...@@ -1727,7 +1728,7 @@ struct proto_ops packet_ops_spkt = {
struct proto_ops packet_ops = { struct proto_ops packet_ops = {
.family = PF_PACKET, .family = PF_PACKET,
.owner = THIS_MODULE,
.release = packet_release, .release = packet_release,
.bind = packet_bind, .bind = packet_bind,
.connect = sock_no_connect, .connect = sock_no_connect,
......
...@@ -1424,7 +1424,7 @@ static struct net_proto_family rose_family_ops = { ...@@ -1424,7 +1424,7 @@ static struct net_proto_family rose_family_ops = {
static struct proto_ops rose_proto_ops = { static struct proto_ops rose_proto_ops = {
.family = PF_ROSE, .family = PF_ROSE,
.owner = THIS_MODULE,
.release = rose_release, .release = rose_release,
.bind = rose_bind, .bind = rose_bind,
.connect = rose_connect, .connect = rose_connect,
......
...@@ -508,6 +508,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -508,6 +508,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
goto out; goto out;
sock_init_data(NULL, newsk); sock_init_data(NULL, newsk);
sk_set_owner(newsk, THIS_MODULE);
newsk->type = SOCK_STREAM; newsk->type = SOCK_STREAM;
...@@ -749,6 +750,7 @@ static int sctp_inet6_supported_addrs(const struct sctp_opt *opt, ...@@ -749,6 +750,7 @@ static int sctp_inet6_supported_addrs(const struct sctp_opt *opt,
static struct proto_ops inet6_seqpacket_ops = { static struct proto_ops inet6_seqpacket_ops = {
.family = PF_INET6, .family = PF_INET6,
.owner = THIS_MODULE,
.release = inet6_release, .release = inet6_release,
.bind = inet6_bind, .bind = inet6_bind,
.connect = inet_dgram_connect, .connect = inet_dgram_connect,
......
...@@ -499,6 +499,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk, ...@@ -499,6 +499,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
goto out; goto out;
sock_init_data(NULL, newsk); sock_init_data(NULL, newsk);
sk_set_owner(newsk, THIS_MODULE);
newsk->type = SOCK_STREAM; newsk->type = SOCK_STREAM;
...@@ -748,6 +749,7 @@ struct notifier_block sctp_inetaddr_notifier = { ...@@ -748,6 +749,7 @@ struct notifier_block sctp_inetaddr_notifier = {
/* Socket operations. */ /* Socket operations. */
struct proto_ops inet_seqpacket_ops = { struct proto_ops inet_seqpacket_ops = {
.family = PF_INET, .family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release, /* Needs to be wrapped... */ .release = inet_release, /* Needs to be wrapped... */
.bind = inet_bind, .bind = inet_bind,
.connect = inet_dgram_connect, .connect = inet_dgram_connect,
......
...@@ -141,36 +141,6 @@ static struct file_operations socket_file_ops = { ...@@ -141,36 +141,6 @@ static struct file_operations socket_file_ops = {
static struct net_proto_family *net_families[NPROTO]; 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) #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static atomic_t net_family_lockct = ATOMIC_INIT(0); static atomic_t net_family_lockct = ATOMIC_INIT(0);
static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED; static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED;
...@@ -535,11 +505,11 @@ struct file_operations bad_sock_fops = { ...@@ -535,11 +505,11 @@ struct file_operations bad_sock_fops = {
void sock_release(struct socket *sock) void sock_release(struct socket *sock)
{ {
if (sock->ops) { if (sock->ops) {
const int family = sock->ops->family; struct module *owner = sock->ops->owner;
sock->ops->release(sock); sock->ops->release(sock);
sock->ops = NULL; sock->ops = NULL;
net_family_put(family); module_put(owner);
} }
if (sock->fasync_list) if (sock->fasync_list)
...@@ -1091,19 +1061,37 @@ int sock_create(int family, int type, int protocol, struct socket **res) ...@@ -1091,19 +1061,37 @@ int sock_create(int family, int type, int protocol, struct socket **res)
sock->type = type; 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; i = -EAFNOSUPPORT;
if (!net_family_get(family)) if (!try_module_get(net_families[family]->owner))
goto out_release;
if ((i = net_families[family]->create(sock, protocol)) < 0)
goto out_release; 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; *res = sock;
security_socket_post_create(sock, family, type, protocol); security_socket_post_create(sock, family, type, protocol);
out: out:
net_family_read_unlock(); net_family_read_unlock();
return i; return i;
out_module_put:
module_put(net_families[family]->owner);
out_release: out_release:
sock_release(sock); sock_release(sock);
goto out; goto out;
...@@ -1288,28 +1276,30 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a ...@@ -1288,28 +1276,30 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
if (err) if (err)
goto out_release; goto out_release;
err = -EAFNOSUPPORT; /*
if (!net_family_get(sock->ops->family)) * We don't need try_module_get here, as the listening socket (sock)
goto out_release; * has the protocol module (sock->ops->owner) held.
*/
__module_get(sock->ops->owner);
err = sock->ops->accept(sock, newsock, sock->file->f_flags); err = sock->ops->accept(sock, newsock, sock->file->f_flags);
if (err < 0) if (err < 0)
goto out_family_put; goto out_module_put;
if (upeer_sockaddr) { if (upeer_sockaddr) {
if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
err = -ECONNABORTED; err = -ECONNABORTED;
goto out_family_put; goto out_module_put;
} }
err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
if (err < 0) if (err < 0)
goto out_family_put; goto out_module_put;
} }
/* File flags are not inherited via accept() unlike another OSes. */ /* File flags are not inherited via accept() unlike another OSes. */
if ((err = sock_map_fd(newsock)) < 0) if ((err = sock_map_fd(newsock)) < 0)
goto out_family_put; goto out_module_put;
security_socket_post_accept(sock, newsock); security_socket_post_accept(sock, newsock);
...@@ -1317,8 +1307,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a ...@@ -1317,8 +1307,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
sockfd_put(sock); sockfd_put(sock);
out: out:
return err; return err;
out_family_put: out_module_put:
net_family_put(sock->ops->family); module_put(sock->ops->owner);
out_release: out_release:
sock_release(newsock); sock_release(newsock);
goto out_put; goto out_put;
......
...@@ -494,6 +494,7 @@ static struct sock * unix_create1(struct socket *sock) ...@@ -494,6 +494,7 @@ static struct sock * unix_create1(struct socket *sock)
atomic_inc(&unix_nr_socks); atomic_inc(&unix_nr_socks);
sock_init_data(sock,sk); sock_init_data(sock,sk);
sk_set_owner(sk, THIS_MODULE);
sk->write_space = unix_write_space; sk->write_space = unix_write_space;
...@@ -1884,7 +1885,7 @@ static int unix_read_proc(char *buffer, char **start, off_t offset, ...@@ -1884,7 +1885,7 @@ static int unix_read_proc(char *buffer, char **start, off_t offset,
struct proto_ops unix_stream_ops = { struct proto_ops unix_stream_ops = {
.family = PF_UNIX, .family = PF_UNIX,
.owner = THIS_MODULE,
.release = unix_release, .release = unix_release,
.bind = unix_bind, .bind = unix_bind,
.connect = unix_stream_connect, .connect = unix_stream_connect,
...@@ -1905,7 +1906,7 @@ struct proto_ops unix_stream_ops = { ...@@ -1905,7 +1906,7 @@ struct proto_ops unix_stream_ops = {
struct proto_ops unix_dgram_ops = { struct proto_ops unix_dgram_ops = {
.family = PF_UNIX, .family = PF_UNIX,
.owner = THIS_MODULE,
.release = unix_release, .release = unix_release,
.bind = unix_bind, .bind = unix_bind,
.connect = unix_dgram_connect, .connect = unix_dgram_connect,
......
...@@ -2551,7 +2551,7 @@ static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr ...@@ -2551,7 +2551,7 @@ static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr
struct proto_ops wanpipe_ops = { struct proto_ops wanpipe_ops = {
.family = PF_WANPIPE, .family = PF_WANPIPE,
.owner = THIS_MODULE,
.release = wanpipe_release, .release = wanpipe_release,
.bind = wanpipe_bind, .bind = wanpipe_bind,
.connect = wanpipe_connect, .connect = wanpipe_connect,
......
...@@ -1323,7 +1323,7 @@ struct net_proto_family x25_family_ops = { ...@@ -1323,7 +1323,7 @@ struct net_proto_family x25_family_ops = {
static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.family = AF_X25, .family = AF_X25,
.owner = THIS_MODULE,
.release = x25_release, .release = x25_release,
.bind = x25_bind, .bind = x25_bind,
.connect = x25_connect, .connect = x25_connect,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment