summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamjae Jeon <linkinjeon@kernel.org>2025-10-21 16:40:04 +0900
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-10-29 14:04:42 +0100
commit71d4e39530eab7382a2889fa0259a49f0370df18 (patch)
tree5095dcc71c2bef95a89f5c5677bfbdf529f85483
parent65aab0bbbf0dccacfb31bcfa1f6f08f0c749780c (diff)
downloadlinux-71d4e39530eab7382a2889fa0259a49f0370df18.tar.gz
linux-71d4e39530eab7382a2889fa0259a49f0370df18.tar.bz2
linux-71d4e39530eab7382a2889fa0259a49f0370df18.zip
ksmbd: browse interfaces list on FSCTL_QUERY_INTERFACE_INFO IOCTL
[ Upstream commit b2d99376c5d61eb60ffdb6c503e4b6c8f9712ddd ] ksmbd.mount will give each interfaces list and bind_interfaces_only flags to ksmbd server. Previously, the interfaces list was sent only when bind_interfaces_only was enabled. ksmbd server browse only interfaces list given from ksmbd.conf on FSCTL_QUERY_INTERFACE_INFO IOCTL. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/smb/server/ksmbd_netlink.h3
-rw-r--r--fs/smb/server/server.h1
-rw-r--r--fs/smb/server/smb2pdu.c4
-rw-r--r--fs/smb/server/transport_ipc.c1
-rw-r--r--fs/smb/server/transport_tcp.c69
-rw-r--r--fs/smb/server/transport_tcp.h1
6 files changed, 41 insertions, 38 deletions
diff --git a/fs/smb/server/ksmbd_netlink.h b/fs/smb/server/ksmbd_netlink.h
index d3c0b985eb8c..475de7289e22 100644
--- a/fs/smb/server/ksmbd_netlink.h
+++ b/fs/smb/server/ksmbd_netlink.h
@@ -107,8 +107,9 @@ struct ksmbd_startup_request {
__u32 smb2_max_credits; /* MAX credits */
__u32 smbd_max_io_size; /* smbd read write size */
__u32 max_connections; /* Number of maximum simultaneous connections */
+ __s8 bind_interfaces_only;
__u32 max_ip_connections; /* Number of maximum connection per ip address */
- __u32 reserved[125]; /* Reserved room */
+ __s8 reserved[499]; /* Reserved room */
__u32 ifc_list_sz; /* interfaces list size */
__s8 ____payload[];
} __packed;
diff --git a/fs/smb/server/server.h b/fs/smb/server/server.h
index 2cb1b855a39e..3cdeda5d0c20 100644
--- a/fs/smb/server/server.h
+++ b/fs/smb/server/server.h
@@ -45,6 +45,7 @@ struct ksmbd_server_config {
unsigned int max_ip_connections;
char *conf[SERVER_CONF_WORK_GROUP + 1];
+ bool bind_interfaces_only;
};
extern struct ksmbd_server_config server_conf;
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 5cf14a910d5b..d2dca5d2f17c 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -37,6 +37,7 @@
#include "mgmt/user_session.h"
#include "mgmt/ksmbd_ida.h"
#include "ndr.h"
+#include "transport_tcp.h"
static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
{
@@ -7423,6 +7424,9 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
if (netdev->type == ARPHRD_LOOPBACK)
continue;
+ if (!ksmbd_find_netdev_name_iface_list(netdev->name))
+ continue;
+
flags = dev_get_flags(netdev);
if (!(flags & IFF_RUNNING))
continue;
diff --git a/fs/smb/server/transport_ipc.c b/fs/smb/server/transport_ipc.c
index 3ca820d0b8d6..85837ba47d90 100644
--- a/fs/smb/server/transport_ipc.c
+++ b/fs/smb/server/transport_ipc.c
@@ -324,6 +324,7 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
ret = ksmbd_set_netbios_name(req->netbios_name);
ret |= ksmbd_set_server_string(req->server_string);
ret |= ksmbd_set_work_group(req->work_group);
+ server_conf.bind_interfaces_only = req->bind_interfaces_only;
ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req),
req->ifc_list_sz);
out:
diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c
index 4ef032e737f3..f07b9e147fe2 100644
--- a/fs/smb/server/transport_tcp.c
+++ b/fs/smb/server/transport_tcp.c
@@ -544,30 +544,37 @@ out_clear:
return ret;
}
+struct interface *ksmbd_find_netdev_name_iface_list(char *netdev_name)
+{
+ struct interface *iface;
+
+ list_for_each_entry(iface, &iface_list, entry)
+ if (!strcmp(iface->name, netdev_name))
+ return iface;
+ return NULL;
+}
+
static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
void *ptr)
{
struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
struct interface *iface;
- int ret, found = 0;
+ int ret;
switch (event) {
case NETDEV_UP:
if (netif_is_bridge_port(netdev))
return NOTIFY_OK;
- list_for_each_entry(iface, &iface_list, entry) {
- if (!strcmp(iface->name, netdev->name)) {
- found = 1;
- if (iface->state != IFACE_STATE_DOWN)
- break;
- ret = create_socket(iface);
- if (ret)
- return NOTIFY_OK;
- break;
- }
+ iface = ksmbd_find_netdev_name_iface_list(netdev->name);
+ if (iface && iface->state == IFACE_STATE_DOWN) {
+ ksmbd_debug(CONN, "netdev-up event: netdev(%s) is going up\n",
+ iface->name);
+ ret = create_socket(iface);
+ if (ret)
+ return NOTIFY_OK;
}
- if (!found && bind_additional_ifaces) {
+ if (!iface && bind_additional_ifaces) {
iface = alloc_iface(kstrdup(netdev->name, GFP_KERNEL));
if (!iface)
return NOTIFY_OK;
@@ -577,19 +584,19 @@ static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
}
break;
case NETDEV_DOWN:
- list_for_each_entry(iface, &iface_list, entry) {
- if (!strcmp(iface->name, netdev->name) &&
- iface->state == IFACE_STATE_CONFIGURED) {
- tcp_stop_kthread(iface->ksmbd_kthread);
- iface->ksmbd_kthread = NULL;
- mutex_lock(&iface->sock_release_lock);
- tcp_destroy_socket(iface->ksmbd_socket);
- iface->ksmbd_socket = NULL;
- mutex_unlock(&iface->sock_release_lock);
-
- iface->state = IFACE_STATE_DOWN;
- break;
- }
+ iface = ksmbd_find_netdev_name_iface_list(netdev->name);
+ if (iface && iface->state == IFACE_STATE_CONFIGURED) {
+ ksmbd_debug(CONN, "netdev-down event: netdev(%s) is going down\n",
+ iface->name);
+ tcp_stop_kthread(iface->ksmbd_kthread);
+ iface->ksmbd_kthread = NULL;
+ mutex_lock(&iface->sock_release_lock);
+ tcp_destroy_socket(iface->ksmbd_socket);
+ iface->ksmbd_socket = NULL;
+ mutex_unlock(&iface->sock_release_lock);
+
+ iface->state = IFACE_STATE_DOWN;
+ break;
}
break;
}
@@ -658,18 +665,6 @@ int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz)
int sz = 0;
if (!ifc_list_sz) {
- struct net_device *netdev;
-
- rtnl_lock();
- for_each_netdev(&init_net, netdev) {
- if (netif_is_bridge_port(netdev))
- continue;
- if (!alloc_iface(kstrdup(netdev->name, GFP_KERNEL))) {
- rtnl_unlock();
- return -ENOMEM;
- }
- }
- rtnl_unlock();
bind_additional_ifaces = 1;
return 0;
}
diff --git a/fs/smb/server/transport_tcp.h b/fs/smb/server/transport_tcp.h
index e338bebe322f..8c9aa624cfe3 100644
--- a/fs/smb/server/transport_tcp.h
+++ b/fs/smb/server/transport_tcp.h
@@ -7,6 +7,7 @@
#define __KSMBD_TRANSPORT_TCP_H__
int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz);
+struct interface *ksmbd_find_netdev_name_iface_list(char *netdev_name);
int ksmbd_tcp_init(void);
void ksmbd_tcp_destroy(void);