@@ -1470,22 +1470,28 @@ int sock_wake_async(struct socket_wq *wq, int how, int band)
EXPORT_SYMBOL(sock_wake_async);
/**
- * __sock_create - creates a socket
- * @net: net namespace
- * @family: protocol family (AF_INET, ...)
- * @type: communication type (SOCK_STREAM, ...)
- * @protocol: protocol (0, ...)
- * @res: new socket
- * @kern: boolean for kernel space sockets
+ * __sock_create - creates a socket
*
- * Creates a new socket and assigns it to @res, passing through LSM.
- * Returns 0 or an error. On failure @res is set to %NULL. @kern must
- * be set to true if the socket resides in kernel space.
- * This function internally uses GFP_KERNEL.
+ * @net: net namespace
+ * @family: protocol family (AF_INET, ...)
+ * @type: communication type (SOCK_STREAM, ...)
+ * @protocol: protocol (0, ...)
+ * @res: new socket
+ * @kern: boolean for kernel space sockets
+ * @hold_net: boolean for netns refcnt
+ *
+ * Creates a new socket and assigns it to @res, passing through LSM.
+ *
+ * @kern must be set to true if userspace cannot touch it via a file
+ * descriptor nor BPF hooks except for LSM. If @hold_net is false,
+ * the caller must ensure that the socket is always freed before @net.
+ *
+ * Context: Process context. This function internally uses GFP_KERNEL.
+ * Return: 0 or an error. On failure @res is set to %NULL.
*/
static int __sock_create(struct net *net, int family, int type, int protocol,
- struct socket **res, int kern)
+ struct socket **res, bool kern, bool hold_net)
{
int err;
struct socket *sock;
@@ -1612,7 +1618,8 @@ static int __sock_create(struct net *net, int family, int type, int protocol,
int sock_create(int family, int type, int protocol, struct socket **res)
{
- return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
+ return __sock_create(current->nsproxy->net_ns, family, type, protocol,
+ res, false, true);
}
EXPORT_SYMBOL(sock_create);
@@ -1628,9 +1635,10 @@ EXPORT_SYMBOL(sock_create);
* Returns 0 or an error. This function internally uses GFP_KERNEL.
*/
-int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
+int sock_create_kern(struct net *net, int family, int type, int protocol,
+ struct socket **res)
{
- return __sock_create(net, family, type, protocol, res, 1);
+ return __sock_create(net, family, type, protocol, res, true, false);
}
EXPORT_SYMBOL(sock_create_kern);
We will introduce a new API to create a kernel socket with netns refcnt held. As a prep, let's add a new hold_net argument to __sock_create(). Note that we still do not pass it down to pf->create() for ease of review; otherwise, this change will be buried in the huge diff. Another option would be to override the kern parameter, which is int, but I chose to change parameters for the following two reasons: 1) Compilers allow us to efficiently make sure that all paths pass the parameters down to sk_alloc() as is. 2) The parameter change breaks out-of-tree drivers, allowing the owners to choose an appropriate API. Regarding 1), there actually was a weird path in smc_ulp_init() that will be fixed up in the following patch. While at it, the kernel-doc is fixed up to render the DESCRIPTION part correctly. scripts/kernel-doc -man net/socket.c | scripts/split-man.pl /tmp/man man /tmp/man/__sock_create.9 Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> --- net/socket.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-)