[PATCH 4/5] connector: Prepare for supporting multiple namespaces
From: Matt Bennett
Date: Wed Jul 01 2020 - 20:28:00 EST
Extend the existing function definitions / call sites to start
passing the network namespace. For now we still only pass the
default namespace.
Signed-off-by: Matt Bennett <matt.bennett@xxxxxxxxxxxxxxxxxxx>
---
Documentation/driver-api/connector.rst | 6 +++---
drivers/connector/cn_proc.c | 5 +++--
drivers/connector/cn_queue.c | 5 +++--
drivers/connector/connector.c | 21 ++++++++++++---------
drivers/hv/hv_utils_transport.c | 6 ++++--
drivers/md/dm-log-userspace-transfer.c | 6 ++++--
drivers/video/fbdev/uvesafb.c | 8 +++++---
drivers/w1/w1_netlink.c | 19 +++++++++++--------
include/linux/connector.h | 24 ++++++++++++++++--------
samples/connector/cn_test.c | 6 ++++--
10 files changed, 65 insertions(+), 41 deletions(-)
diff --git a/Documentation/driver-api/connector.rst b/Documentation/driver-api/connector.rst
index c100c7482289..4fb1f73d76ad 100644
--- a/Documentation/driver-api/connector.rst
+++ b/Documentation/driver-api/connector.rst
@@ -25,9 +25,9 @@ handling, etc... The Connector driver allows any kernelspace agents to use
netlink based networking for inter-process communication in a significantly
easier way::
- int cn_add_callback(struct cb_id *id, char *name, void (*callback) (struct cn_msg *, struct netlink_skb_parms *));
- void cn_netlink_send_multi(struct cn_msg *msg, u16 len, u32 portid, u32 __group, int gfp_mask);
- void cn_netlink_send(struct cn_msg *msg, u32 portid, u32 __group, int gfp_mask);
+ int cn_add_callback(struct cb_id *id, char *name, void (*callback) (struct net *, struct cn_msg *, struct netlink_skb_parms *));
+ void cn_netlink_send_multi(struct net *net, struct cn_msg *msg, u16 len, u32 portid, u32 __group, int gfp_mask);
+ void cn_netlink_send(struct net *net, struct cn_msg *msg, u32 portid, u32 __group, int gfp_mask);
struct cb_id
{
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index d90aea555a21..9202be177a30 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -16,6 +16,7 @@
#include <linux/ptrace.h>
#include <linux/atomic.h>
#include <linux/pid_namespace.h>
+#include <net/net_namespace.h>
#include <linux/cn_proc.h>
#include <linux/local_lock.h>
@@ -61,7 +62,7 @@ static inline void send_msg(struct cn_msg *msg)
*
* If cn_netlink_send() fails, the data is not sent.
*/
- cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_NOWAIT);
+ cn_netlink_send(&init_net, msg, 0, CN_IDX_PROC, GFP_NOWAIT);
local_unlock(&local_event.lock);
}
@@ -343,7 +344,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
* cn_proc_mcast_ctl
* @data: message sent from userspace via the connector
*/
-static void cn_proc_mcast_ctl(struct cn_msg *msg,
+static void cn_proc_mcast_ctl(struct net *net, struct cn_msg *msg,
struct netlink_skb_parms *nsp)
{
enum proc_cn_mcast_op *mc_op = NULL;
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
index a82ceeb37f26..22fdd2b149af 100644
--- a/drivers/connector/cn_queue.c
+++ b/drivers/connector/cn_queue.c
@@ -16,11 +16,12 @@
#include <linux/suspend.h>
#include <linux/connector.h>
#include <linux/delay.h>
+#include <net/net_namespace.h>
static struct cn_callback_entry *
cn_queue_alloc_callback_entry(struct cn_queue_dev *dev, const char *name,
struct cb_id *id,
- void (*callback)(struct cn_msg *,
+ void (*callback)(struct net *, struct cn_msg *,
struct netlink_skb_parms *))
{
struct cn_callback_entry *cbq;
@@ -58,7 +59,7 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
struct cb_id *id,
- void (*callback)(struct cn_msg *,
+ void (*callback)(struct net *, struct cn_msg *,
struct netlink_skb_parms *))
{
struct cn_callback_entry *cbq, *__cbq;
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 2d22d6bf52f2..82fcaa4d8be3 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -58,8 +58,8 @@ static int cn_already_initialized;
* The message is sent to, the portid if given, the group if given, both if
* both, or if both are zero then the group is looked up and sent there.
*/
-int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 __group,
- gfp_t gfp_mask)
+int cn_netlink_send_mult(struct net *net, struct cn_msg *msg, u16 len,
+ u32 portid, u32 __group, gfp_t gfp_mask)
{
struct cn_callback_entry *__cbq;
unsigned int size;
@@ -118,17 +118,18 @@ int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 __group,
EXPORT_SYMBOL_GPL(cn_netlink_send_mult);
/* same as cn_netlink_send_mult except msg->len is used for len */
-int cn_netlink_send(struct cn_msg *msg, u32 portid, u32 __group,
- gfp_t gfp_mask)
+int cn_netlink_send(struct net *net, struct cn_msg *msg, u32 portid,
+ u32 __group, gfp_t gfp_mask)
{
- return cn_netlink_send_mult(msg, msg->len, portid, __group, gfp_mask);
+ return cn_netlink_send_mult(net, msg, msg->len, portid, __group,
+ gfp_mask);
}
EXPORT_SYMBOL_GPL(cn_netlink_send);
/*
* Callback helper - queues work and setup destructor for given data.
*/
-static int cn_call_callback(struct sk_buff *skb)
+static int cn_call_callback(struct net *net, struct sk_buff *skb)
{
struct nlmsghdr *nlh;
struct cn_callback_entry *i, *cbq = NULL;
@@ -153,7 +154,7 @@ static int cn_call_callback(struct sk_buff *skb)
spin_unlock_bh(&dev->cbdev->queue_lock);
if (cbq != NULL) {
- cbq->callback(msg, nsp);
+ cbq->callback(net, msg, nsp);
kfree_skb(skb);
cn_queue_release_callback(cbq);
err = 0;
@@ -172,6 +173,8 @@ static void cn_rx_skb(struct sk_buff *skb)
struct nlmsghdr *nlh;
int len, err;
+ struct net *net = sock_net(skb->sk);
+
if (skb->len >= NLMSG_HDRLEN) {
nlh = nlmsg_hdr(skb);
len = nlmsg_len(nlh);
@@ -181,7 +184,7 @@ static void cn_rx_skb(struct sk_buff *skb)
len > CONNECTOR_MAX_MSG_SIZE)
return;
- err = cn_call_callback(skb_get(skb));
+ err = cn_call_callback(net, skb_get(skb));
if (err < 0)
kfree_skb(skb);
}
@@ -194,7 +197,7 @@ static void cn_rx_skb(struct sk_buff *skb)
* May sleep.
*/
int cn_add_callback(struct cb_id *id, const char *name,
- void (*callback)(struct cn_msg *,
+ void (*callback)(struct net *, struct cn_msg *,
struct netlink_skb_parms *))
{
int err;
diff --git a/drivers/hv/hv_utils_transport.c b/drivers/hv/hv_utils_transport.c
index eb2833d2b5d0..1a67efe59e91 100644
--- a/drivers/hv/hv_utils_transport.c
+++ b/drivers/hv/hv_utils_transport.c
@@ -8,6 +8,7 @@
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/poll.h>
+#include <net/net_namespace.h>
#include "hyperv_vmbus.h"
#include "hv_utils_transport.h"
@@ -181,7 +182,8 @@ static int hvt_op_release(struct inode *inode, struct file *file)
return 0;
}
-static void hvt_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+static void hvt_cn_callback(struct net *net, struct cn_msg *msg,
+ struct netlink_skb_parms *nsp)
{
struct hvutil_transport *hvt, *hvt_found = NULL;
@@ -231,7 +233,7 @@ int hvutil_transport_send(struct hvutil_transport *hvt, void *msg, int len,
cn_msg->id.val = hvt->cn_id.val;
cn_msg->len = len;
memcpy(cn_msg->data, msg, len);
- ret = cn_netlink_send(cn_msg, 0, 0, GFP_ATOMIC);
+ ret = cn_netlink_send(&init_net, cn_msg, 0, 0, GFP_ATOMIC);
kfree(cn_msg);
/*
* We don't know when netlink messages are delivered but unlike
diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c
index fdf8ec304f8d..0e835acf14da 100644
--- a/drivers/md/dm-log-userspace-transfer.c
+++ b/drivers/md/dm-log-userspace-transfer.c
@@ -12,6 +12,7 @@
#include <linux/connector.h>
#include <linux/device-mapper.h>
#include <linux/dm-log-userspace.h>
+#include <net/net_namespace.h>
#include "dm-log-userspace-transfer.h"
@@ -66,7 +67,7 @@ static int dm_ulog_sendto_server(struct dm_ulog_request *tfr)
msg->seq = tfr->seq;
msg->len = sizeof(struct dm_ulog_request) + tfr->data_size;
- r = cn_netlink_send(msg, 0, 0, gfp_any());
+ r = cn_netlink_send(&init_net, msg, 0, 0, gfp_any());
return r;
}
@@ -130,7 +131,8 @@ static int fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr)
* This is the connector callback that delivers data
* that was sent from userspace.
*/
-static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+static void cn_ulog_callback(struct net *net, struct cn_msg *msg,
+ struct netlink_skb_parms *nsp)
{
struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1);
diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c
index def14ac0ebe1..f9b6ed7b97f2 100644
--- a/drivers/video/fbdev/uvesafb.c
+++ b/drivers/video/fbdev/uvesafb.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <video/edid.h>
#include <video/uvesafb.h>
+#include <net/net_namespace.h>
#ifdef CONFIG_X86
#include <video/vga.h>
#endif
@@ -69,7 +70,8 @@ static DEFINE_MUTEX(uvfb_lock);
* find the kernel part of the task struct, copy the registers and
* the buffer contents and then complete the task.
*/
-static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+static void uvesafb_cn_callback(struct net *net, struct cn_msg *msg,
+ struct netlink_skb_parms *nsp)
{
struct uvesafb_task *utask;
struct uvesafb_ktask *task;
@@ -194,7 +196,7 @@ static int uvesafb_exec(struct uvesafb_ktask *task)
uvfb_tasks[seq] = task;
mutex_unlock(&uvfb_lock);
- err = cn_netlink_send(m, 0, 0, GFP_KERNEL);
+ err = cn_netlink_send(&init_net, m, 0, 0, GFP_KERNEL);
if (err == -ESRCH) {
/*
* Try to start the userspace helper if sending
@@ -206,7 +208,7 @@ static int uvesafb_exec(struct uvesafb_ktask *task)
pr_err("make sure that the v86d helper is installed and executable\n");
} else {
v86d_started = 1;
- err = cn_netlink_send(m, 0, 0, gfp_any());
+ err = cn_netlink_send(&init_net, m, 0, 0, gfp_any());
if (err == -ENOBUFS)
err = 0;
}
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index fa490aa4407c..246844b61613 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -7,6 +7,7 @@
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/connector.h>
+#include <net/net_namespace.h>
#include "w1_internal.h"
#include "w1_netlink.h"
@@ -64,8 +65,8 @@ static void w1_unref_block(struct w1_cb_block *block)
if (atomic_sub_return(1, &block->refcnt) == 0) {
u16 len = w1_reply_len(block);
if (len) {
- cn_netlink_send_mult(block->first_cn, len,
- block->portid, 0, GFP_KERNEL);
+ cn_netlink_send_mult(&init_net, block->first_cn, len,
+ block->portid, 0, GFP_KERNEL);
}
kfree(block);
}
@@ -83,7 +84,8 @@ static void w1_reply_make_space(struct w1_cb_block *block, u16 space)
{
u16 len = w1_reply_len(block);
if (len + space >= block->maxlen) {
- cn_netlink_send_mult(block->first_cn, len, block->portid, 0, GFP_KERNEL);
+ cn_netlink_send_mult(&init_net, block->first_cn, len,
+ block->portid, 0, GFP_KERNEL);
block->first_cn->len = 0;
block->cn = NULL;
block->msg = NULL;
@@ -201,7 +203,7 @@ static void w1_netlink_send_error(struct cn_msg *cn, struct w1_netlink_msg *msg,
packet.cn.len = sizeof(packet.msg);
packet.msg.len = 0;
packet.msg.status = (u8)-error;
- cn_netlink_send(&packet.cn, portid, 0, GFP_KERNEL);
+ cn_netlink_send(&init_net, &packet.cn, portid, 0, GFP_KERNEL);
}
/**
@@ -228,7 +230,7 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
memcpy(&packet.msg, msg, sizeof(*msg));
packet.msg.len = 0;
- cn_netlink_send(&packet.cn, 0, 0, GFP_KERNEL);
+ cn_netlink_send(&init_net, &packet.cn, 0, 0, GFP_KERNEL);
}
static void w1_send_slave(struct w1_master *dev, u64 rn)
@@ -421,7 +423,7 @@ static int w1_process_command_root(struct cn_msg *req_cn, u32 portid)
mutex_lock(&w1_mlock);
list_for_each_entry(dev, &w1_masters, w1_master_entry) {
if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) {
- cn_netlink_send(cn, portid, 0, GFP_KERNEL);
+ cn_netlink_send(&init_net, cn, portid, 0, GFP_KERNEL);
cn->len = sizeof(struct w1_netlink_msg);
msg->len = 0;
id = (u32 *)msg->data;
@@ -432,7 +434,7 @@ static int w1_process_command_root(struct cn_msg *req_cn, u32 portid)
cn->len += sizeof(*id);
id++;
}
- cn_netlink_send(cn, portid, 0, GFP_KERNEL);
+ cn_netlink_send(&init_net, cn, portid, 0, GFP_KERNEL);
mutex_unlock(&w1_mlock);
kfree(cn);
@@ -532,7 +534,8 @@ static void w1_list_count_cmds(struct w1_netlink_msg *msg, int *cmd_count,
}
}
-static void w1_cn_callback(struct cn_msg *cn, struct netlink_skb_parms *nsp)
+static void w1_cn_callback(struct net *net, struct cn_msg *cn,
+ struct netlink_skb_parms *nsp)
{
struct w1_netlink_msg *msg = (struct w1_netlink_msg *)(cn + 1);
struct w1_slave *sl;
diff --git a/include/linux/connector.h b/include/linux/connector.h
index cb732643471b..8e9385eb18f8 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -40,7 +40,8 @@ struct cn_callback_entry {
struct cn_queue_dev *pdev;
struct cn_callback_id id;
- void (*callback) (struct cn_msg *, struct netlink_skb_parms *);
+ void (*callback)(struct net *, struct cn_msg *,
+ struct netlink_skb_parms *);
u32 seq, group;
};
@@ -62,10 +63,12 @@ struct cn_dev {
* in-kernel users.
* @name: connector's callback symbolic name.
* @callback: connector's callback.
- * parameters are %cn_msg and the sender's credentials
+ * parameters are network namespace, %cn_msg and
+ * the sender's credentials
*/
int cn_add_callback(struct cb_id *id, const char *name,
- void (*callback)(struct cn_msg *, struct netlink_skb_parms *));
+ void (*callback)(struct net *, struct cn_msg *,
+ struct netlink_skb_parms *));
/**
* cn_del_callback() - Unregisters new callback with connector core.
*
@@ -75,8 +78,9 @@ void cn_del_callback(struct cb_id *id);
/**
- * cn_netlink_send_mult - Sends message to the specified groups.
+ * cn_netlink_send_mult - Sends messages to the specified groups.
*
+ * @net: network namespace
* @msg: message header(with attached data).
* @len: Number of @msg to be sent.
* @portid: destination port.
@@ -96,11 +100,13 @@ void cn_del_callback(struct cb_id *id);
*
* If there are no listeners for given group %-ESRCH can be returned.
*/
-int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 group, gfp_t gfp_mask);
+int cn_netlink_send_mult(struct net *net, struct cn_msg *msg, u16 len,
+ u32 portid, u32 group, gfp_t gfp_mask);
/**
- * cn_netlink_send_mult - Sends message to the specified groups.
+ * cn_netlink_send - Sends message to the specified groups.
*
+ * @net: network namespace
* @msg: message header(with attached data).
* @portid: destination port.
* If non-zero the message will be sent to the given port,
@@ -119,11 +125,13 @@ int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 group, gfp
*
* If there are no listeners for given group %-ESRCH can be returned.
*/
-int cn_netlink_send(struct cn_msg *msg, u32 portid, u32 group, gfp_t gfp_mask);
+int cn_netlink_send(struct net *net, struct cn_msg *msg, u32 portid, u32 group,
+ gfp_t gfp_mask);
int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
struct cb_id *id,
- void (*callback)(struct cn_msg *, struct netlink_skb_parms *));
+ void (*callback)(struct net *, struct cn_msg *,
+ struct netlink_skb_parms *));
void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);
void cn_queue_release_callback(struct cn_callback_entry *);
diff --git a/samples/connector/cn_test.c b/samples/connector/cn_test.c
index 0958a171d048..9eaf40bbd714 100644
--- a/samples/connector/cn_test.c
+++ b/samples/connector/cn_test.c
@@ -16,13 +16,15 @@
#include <linux/timer.h>
#include <linux/connector.h>
+#include <net/net_namespace.h>
static struct cb_id cn_test_id = { CN_NETLINK_USERS + 3, 0x456 };
static char cn_test_name[] = "cn_test";
static struct sock *nls;
static struct timer_list cn_test_timer;
-static void cn_test_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+static void cn_test_callback(struct net *net, struct cn_msg *msg,
+ struct netlink_skb_parms *nsp)
{
pr_info("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
__func__, jiffies, msg->id.idx, msg->id.val,
@@ -132,7 +134,7 @@ static void cn_test_timer_func(struct timer_list *unused)
memcpy(m + 1, data, m->len);
- cn_netlink_send(m, 0, 0, GFP_ATOMIC);
+ cn_netlink_send(&init_net, m, 0, 0, GFP_ATOMIC);
kfree(m);
}
--
2.27.0