From: David Laight <david.laight.linux@gmail.com>
To: Alex Goltsev <sasha.goltsev777@gmail.com>
Cc: davem@davemloft.net, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, Al Viro <viro@zeniv.linux.org.uk>
Subject: Re: [PATCH v2] net: add sock_open() with flags for socket creation
Date: Sun, 21 Jun 2026 13:57:46 +0100 [thread overview]
Message-ID: <20260621135746.067a93be@pumpkin> (raw)
In-Reply-To: <CAEKmD4K-v_srabQDJCfqaqA6vssk-Hg-mLHEdTsphTBLmQVjnw@mail.gmail.com>
On Sun, 21 Jun 2026 14:05:40 +0300
Alex Goltsev <sasha.goltsev777@gmail.com> wrote:
> From a9316957e594708dfb4258ad968fe88666c9b736 Mon Sep 17 00:00:00 2001
> From: 0-x-0-0 <sasha.goltsev777@gmail.com>
> Date: Sun, 21 Jun 2026 13:24:29 +0300
> Subject: [PATCH v2] net: add sock_open() with flags for socket creation
A) There is no info here.
B) You've not said why this is of any use.
C) It isn't a bug fix so would go into net-next
D) net-next is closed.
David
>
> ---
> Changes in V2:
> - Replaced the use of plain integer constants for flags with proper
> enums to improve readability and type safety.
> - `sock_open` is intentionally left as a regular exported symbol rather
> than being moved to a header as `static inline`. This is because it
> dereferences `current->nsproxy->net_ns`, which would require pulling
> in heavy headers like <linux/sched.h> and <linux/nsproxy.h> into the
> already widely-used <linux/net.h>, causing unnecessary header bloat
> and potential circular dependencies.
> - Introduced two new creation flags for specialized use cases within
> kernel modules:
>
> * SOCK_CREATE_NOLSM: This flag allows a kernel module to bypass
> LSM hooks during socket creation. This
> enables a micro-optimization for kernel-internal sockets where
> the security check is known *a priori* to be a no-op (e.g., for
> specific configurations or high-performance paths).
> This is safe because the API is restricted to in-kernel (LKM)
> contexts only, and does not weaken the security boundary for
> user-triggered socket creation.
>
> * SOCK_CREATE_NOWARN: This flag suppresses the standard warning
> messages on creation failure. This is useful for callers in the
> kernel that probe for protocol support and handle the error
> gracefully, without wanting to pollute the kernel log with
> misleading warnings.
>
> Signed-off-by: Alexander Goltsev <sasha.goltsev777@gmail.com>
> ---
> include/linux/net.h | 22 ++++++++
> net/socket.c | 133 +++++++++++++++++++++++++++++++++++++-------
> 2 files changed, 134 insertions(+), 21 deletions(-)
>
> diff --git a/include/linux/net.h b/include/linux/net.h
> index f268f395c..6367c00db 100644
> --- a/include/linux/net.h
> +++ b/include/linux/net.h
> @@ -116,6 +116,22 @@ enum sock_shutdown_cmd {
> SHUT_RDWR,
> };
> +/**
> + * enum sock_create_flags - socket creation flags
> + * @SOCK_CREATE_KERN: creates a kernel socket
> + * @SOCK_CREATE_USER: creates a regular socket
> + * @SOCK_CREATE_LITE: creates a lite socket
> + * @SOCK_CREATE_NOLSM: disables LSM
> + * @SOCK_CREATE_NOWARN: disables warning
> + */
> +enum sock_create_flags {
> + SOCK_CREATE_KERN = BIT(0),
> + SOCK_CREATE_USER = BIT(1),
> + SOCK_CREATE_LITE = BIT(2),
> + SOCK_CREATE_NOLSM = BIT(3),
> + SOCK_CREATE_NOWARN = BIT(4),
> +};
> +
> struct socket_wq {
> /* Note: wait MUST be first field of socket_wq */
> wait_queue_head_t wait;
> @@ -275,6 +291,12 @@ void sock_unregister(int family);
> bool sock_is_registered(int family);
> int __sock_create(struct net *net, int family, int type, int proto,
> struct socket **res, int kern);
> +int __sock_create_flags(struct net *net, int family, int type, int protocol,
> + struct socket **res, int kern, int flags);
> +int __sock_create_lite_flags(int family, int type, int protocol,
> + struct socket **res, int flags);
> +int sock_open(struct net *net, int family,
> + int type, int protocol, struct socket **res, int flags);
> int sock_create(int family, int type, int proto, struct socket **res);
> int sock_create_kern(struct net *net, int family, int type, int proto,
> struct socket **res);
> int sock_create_lite(int family, int type, int proto, struct socket **res);
> diff --git a/net/socket.c b/net/socket.c
> index 63c69a0fa..2359fd5bf 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -1425,26 +1425,28 @@ static long sock_ioctl(struct file *file,
> unsigned cmd, unsigned long arg)
> }
> /**
> - * sock_create_lite - creates a socket
> + * __sock_create_lite_flags - creates a socket (with flags)
> * @family: protocol family (AF_INET, ...)
> * @type: communication type (SOCK_STREAM, ...)
> * @protocol: protocol (0, ...)
> * @res: new socket
> + * @flags: defines socket creation flags
> *
> * Creates a new socket and assigns it to @res, passing through LSM.
> * The new socket initialization is not complete, see kernel_accept().
> * Returns 0 or an error. On failure @res is set to %NULL.
> * This function internally uses GFP_KERNEL.
> */
> -
> -int sock_create_lite(int family, int type, int protocol, struct socket **res)
> +int __sock_create_lite_flags(int family, int type, int protocol,
> struct socket **res, int flags)
> {
> int err;
> struct socket *sock = NULL;
> - err = security_socket_create(family, type, protocol, 1);
> - if (err)
> - goto out;
> + if (!(flags & SOCK_CREATE_NOLSM)) {
> + err = security_socket_create(family, type, protocol, 1);
> + if (err)
> + goto out;
> + }
> sock = sock_alloc();
> if (!sock) {
> @@ -1453,9 +1455,11 @@ int sock_create_lite(int family, int type, int
> protocol, struct socket **res)
> }
> sock->type = type;
> - err = security_socket_post_create(sock, family, type, protocol, 1);
> - if (err)
> - goto out_release;
> + if (!(flags & SOCK_CREATE_NOLSM)) {
> + err = security_socket_post_create(sock, family, type, protocol, 1);
> + if (err)
> + goto out_release;
> + }
> out:
> *res = sock;
> @@ -1465,6 +1469,25 @@ int sock_create_lite(int family, int type, int
> protocol, struct socket **res)
> sock = NULL;
> goto out;
> }
> +EXPORT_SYMBOL(__sock_create_lite_flags);
> +
> +/**
> + * sock_create_lite - creates a socket
> + * @family: protocol family (AF_INET, ...)
> + * @type: communication type (SOCK_STREAM, ...)
> + * @protocol: protocol (0, ...)
> + * @res: new socket
> + *
> + * Creates a new socket and assigns it to @res, passing through LSM.
> + * The new socket initialization is not complete, see kernel_accept().
> + * Returns 0 or an error. On failure @res is set to %NULL.
> + * This function internally uses GFP_KERNEL.
> + */
> +
> +int sock_create_lite(int family, int type, int protocol, struct socket **res)
> +{
> + return __sock_create_lite_flags(family, type, protocol, res, 0);
> +}
> EXPORT_SYMBOL(sock_create_lite);
> /* No kernel lock held - perfect */
> @@ -1563,22 +1586,23 @@ int sock_wake_async(struct socket_wq *wq, int
> how, int band)
> EXPORT_SYMBOL(sock_wake_async);
> /**
> - * __sock_create - creates a socket
> + * __sock_create_flags - creates a socket (with flags)
> * @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
> + * @flags: defines socket creation flags
> *
> * 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.
> */
> -
> -int __sock_create(struct net *net, int family, int type, int protocol,
> - struct socket **res, int kern)
> +int __sock_create_flags(struct net *net, int family,
> + int type, int protocol, struct socket **res,
> + int kern, int flags)
> {
> int err;
> struct socket *sock;
> @@ -1598,14 +1622,18 @@ int __sock_create(struct net *net, int family,
> int type, int protocol,
> deadlock in module load.
> */
> if (family == PF_INET && type == SOCK_PACKET) {
> - pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
> + if (!(flags & SOCK_CREATE_NOWARN)) {
> + pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
> current->comm);
> + }
> family = PF_PACKET;
> }
> - err = security_socket_create(family, type, protocol, kern);
> - if (err)
> - return err;
> + if (!(flags & SOCK_CREATE_NOLSM)) {
> + err = security_socket_create(family, type, protocol, kern);
> + if (err)
> + return err;
> + }
> /*
> * Allocate the socket and allow the family to set things up. if
> @@ -1614,7 +1642,8 @@ int __sock_create(struct net *net, int family,
> int type, int protocol,
> */
> sock = sock_alloc();
> if (!sock) {
> - net_warn_ratelimited("socket: no more sockets\n");
> + if (!(flags & SOCK_CREATE_NOWARN))
> + net_warn_ratelimited("socket: no more sockets\n");
> return -ENFILE; /* Not exactly a match, but its the
> closest posix thing */
> }
> @@ -1671,9 +1700,12 @@ int __sock_create(struct net *net, int family,
> int type, int protocol,
> * module can have its refcnt decremented
> */
> module_put(pf->owner);
> - err = security_socket_post_create(sock, family, type, protocol, kern);
> - if (err)
> - goto out_sock_release;
> +
> + if (!(flags & SOCK_CREATE_NOLSM)) {
> + err = security_socket_post_create(sock, family, type, protocol, kern);
> + if (err)
> + goto out_sock_release;
> + }
> *res = sock;
> return 0;
> @@ -1691,6 +1723,28 @@ int __sock_create(struct net *net, int family,
> int type, int protocol,
> rcu_read_unlock();
> goto out_sock_release;
> }
> +EXPORT_SYMBOL(__sock_create_flags);
> +
> +/**
> + * __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
> + *
> + * 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.
> + */
> +
> +int __sock_create(struct net *net, int family, int type, int protocol,
> + struct socket **res, int kern)
> +{
> + return __sock_create_flags(net, family, type, protocol, res, kern, 0);
> +}
> EXPORT_SYMBOL(__sock_create);
> /**
> @@ -1710,6 +1764,43 @@ int sock_create(int family, int type, int
> protocol, struct socket **res)
> }
> EXPORT_SYMBOL(sock_create);
> +/**
> + * sock_open - creates a socket (with flags)
> + * @net: net namespace (may be NULL in non-SOCK_CREATE_KERN modes)
> + * @family: protocol family (AF_INET, ...)
> + * @type: communication type (SOCK_STREAM, ...)
> + * @protocol: protocol (0, ...)
> + * @res: new socket
> + * @flags: socket creation flags
> + *
> + * Unified entry point for socket creation with flags.
> + * Returns 0 or an error. This function internally uses GFP_KERNEL.
> + */
> +int sock_open(struct net *net, int family,
> + int type, int protocol, struct socket **res,
> + int flags)
> +{
> + int type_bits = flags & (SOCK_CREATE_KERN | SOCK_CREATE_USER |
> SOCK_CREATE_LITE);
> + int optional_flags = flags & ~(SOCK_CREATE_KERN | SOCK_CREATE_USER |
> SOCK_CREATE_LITE);
> +
> + if (type_bits == 0 || (type_bits & (type_bits - 1)) != 0)
> + return -EINVAL;
> +
> + if (optional_flags & ~(SOCK_CREATE_NOLSM | SOCK_CREATE_NOWARN))
> + return -EINVAL;
> +
> + switch (type_bits) {
> + case SOCK_CREATE_KERN: return __sock_create_flags(net, family, type, protocol,
> + res, 1, optional_flags);
> + case SOCK_CREATE_USER: return __sock_create_flags(current->nsproxy->net_ns,
> + family, type, protocol, res, 0, optional_flags);
> + case SOCK_CREATE_LITE: return __sock_create_lite_flags(family,
> + type, protocol, res, optional_flags);
> + default: return -EINVAL;
> + }
> +}
> +EXPORT_SYMBOL(sock_open);
> +
> /**
> * sock_create_kern - creates a socket (kernel space)
> * @net: net namespace
next prev parent reply other threads:[~2026-06-21 12:57 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-18 13:06 [PATCH] net: add sock_open() for unified socket creation Alex Goltsev
2026-06-18 21:12 ` Al Viro
2026-06-19 10:35 ` Alex Goltsev
2026-06-19 16:34 ` Al Viro
2026-06-19 17:54 ` Alex Goltsev
2026-06-21 11:05 ` [PATCH v2] net: add sock_open() with flags for " Alex Goltsev
2026-06-21 12:57 ` David Laight [this message]
2026-06-21 13:59 ` Andrew Lunn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260621135746.067a93be@pumpkin \
--to=david.laight.linux@gmail.com \
--cc=davem@davemloft.net \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=sasha.goltsev777@gmail.com \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox