Skip to content

Commit a79af59

Browse files
Frank Filzdavem330
authored andcommitted
[NET]: Fix module reference counts for loadable protocol modules
I have been experimenting with loadable protocol modules, and ran into several issues with module reference counting. The first issue was that __module_get failed at the BUG_ON check at the top of the routine (checking that my module reference count was not zero) when I created the first socket. When sk_alloc() is called, my module reference count was still 0. When I looked at why sctp didn't have this problem, I discovered that sctp creates a control socket during module init (when the module ref count is not 0), which keeps the reference count non-zero. This section has been updated to address the point Stephen raised about checking the return value of try_module_get(). The next problem arose when my socket init routine returned an error. This resulted in my module reference count being decremented below 0. My socket ops->release routine was also being called. The issue here is that sock_release() calls the ops->release routine and decrements the ref count if sock->ops is not NULL. Since the socket probably didn't get correctly initialized, this should not be done, so we will set sock->ops to NULL because we will not call try_module_get(). While searching for another bug, I also noticed that sys_accept() has a possibility of doing a module_put() when it did not do an __module_get so I re-ordered the call to security_socket_accept(). Signed-off-by: Frank Filz <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9356b8f commit a79af59

File tree

2 files changed

+20
-13
lines changed

2 files changed

+20
-13
lines changed

net/core/sock.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -660,16 +660,20 @@ struct sock *sk_alloc(int family, unsigned int __nocast priority,
660660
sock_lock_init(sk);
661661
}
662662

663-
if (security_sk_alloc(sk, family, priority)) {
664-
if (slab != NULL)
665-
kmem_cache_free(slab, sk);
666-
else
667-
kfree(sk);
668-
sk = NULL;
669-
} else
670-
__module_get(prot->owner);
663+
if (security_sk_alloc(sk, family, priority))
664+
goto out_free;
665+
666+
if (!try_module_get(prot->owner))
667+
goto out_free;
671668
}
672669
return sk;
670+
671+
out_free:
672+
if (slab != NULL)
673+
kmem_cache_free(slab, sk);
674+
else
675+
kfree(sk);
676+
return NULL;
673677
}
674678

675679
void sk_free(struct sock *sk)

net/socket.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,8 +1145,11 @@ static int __sock_create(int family, int type, int protocol, struct socket **res
11451145
if (!try_module_get(net_families[family]->owner))
11461146
goto out_release;
11471147

1148-
if ((err = net_families[family]->create(sock, protocol)) < 0)
1148+
if ((err = net_families[family]->create(sock, protocol)) < 0) {
1149+
sock->ops = NULL;
11491150
goto out_module_put;
1151+
}
1152+
11501153
/*
11511154
* Now to bump the refcnt of the [loadable] module that owns this
11521155
* socket at sock_release time we decrement its refcnt.
@@ -1360,16 +1363,16 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
13601363
newsock->type = sock->type;
13611364
newsock->ops = sock->ops;
13621365

1363-
err = security_socket_accept(sock, newsock);
1364-
if (err)
1365-
goto out_release;
1366-
13671366
/*
13681367
* We don't need try_module_get here, as the listening socket (sock)
13691368
* has the protocol module (sock->ops->owner) held.
13701369
*/
13711370
__module_get(newsock->ops->owner);
13721371

1372+
err = security_socket_accept(sock, newsock);
1373+
if (err)
1374+
goto out_release;
1375+
13731376
err = sock->ops->accept(sock, newsock, sock->file->f_flags);
13741377
if (err < 0)
13751378
goto out_release;

0 commit comments

Comments
 (0)