Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d928215 authored by Srinivasarao P's avatar Srinivasarao P
Browse files

Reverting rmnet, incrementalfs changes from android-4.19.112



5043d35d net: rmnet: fix packet forwarding in rmnet bridge mode
8cf81bf8 net: rmnet: fix bridge mode bugs
79978164 net: rmnet: use upper/lower device infrastructure
48c5bfbb net: rmnet: do not allow to change mux id if mux id is duplicated
7111ec09 net: rmnet: remove rcu_read_lock in rmnet_force_unassociate_device()
5cd211aa net: rmnet: fix suspicious RCU usage
be045358 net: rmnet: fix NULL pointer dereference in rmnet_changelink()
71ae5b69 net: rmnet: fix NULL pointer dereference in rmnet_newlink()
1530be50 ANDROID: Incremental fs: Add INCFS_IOC_PERMIT_FILL
73e7d656 ANDROID: Incremental fs: Remove signature checks from kernel
53809634 ANDROID: Incremental fs: Pad hash blocks
70539f7c ANDROID: Incremental fs: Make fill block an ioctl
e2999b39 ANDROID: Incremental fs: Remove all access_ok checks

Change-Id: I4d874a3e4f146064031bfa63a611b0832e9ec82a
Signed-off-by: default avatarSrinivasarao P <spathi@codeaurora.org>
parent 57f27753
Loading
Loading
Loading
Loading
+95 −91
Original line number Diff line number Diff line
@@ -22,6 +22,25 @@
#include "rmnet_vnd.h"
#include "rmnet_private.h"

/* Locking scheme -
 * The shared resource which needs to be protected is realdev->rx_handler_data.
 * For the writer path, this is using rtnl_lock(). The writer paths are
 * rmnet_newlink(), rmnet_dellink() and rmnet_force_unassociate_device(). These
 * paths are already called with rtnl_lock() acquired in. There is also an
 * ASSERT_RTNL() to ensure that we are calling with rtnl acquired. For
 * dereference here, we will need to use rtnl_dereference(). Dev list writing
 * needs to happen with rtnl_lock() acquired for netdev_master_upper_dev_link().
 * For the reader path, the real_dev->rx_handler_data is called in the TX / RX
 * path. We only need rcu_read_lock() for these scenarios. In these cases,
 * the rcu_read_lock() is held in __dev_queue_xmit() and
 * netif_receive_skb_internal(), so readers need to use rcu_dereference_rtnl()
 * to get the relevant information. For dev list reading, we again acquire
 * rcu_read_lock() in rmnet_dellink() for netdev_master_upper_dev_get_rcu().
 * We also use unregister_netdevice_many() to free all rmnet devices in
 * rmnet_force_unassociate_device() so we dont lose the rtnl_lock() and free in
 * same context.
 */

/* Local Definitions and Declarations */

static const struct nla_policy rmnet_policy[IFLA_RMNET_MAX + 1] = {
@@ -41,10 +60,9 @@ rmnet_get_port_rtnl(const struct net_device *real_dev)
	return rtnl_dereference(real_dev->rx_handler_data);
}

static int rmnet_unregister_real_device(struct net_device *real_dev)
static int rmnet_unregister_real_device(struct net_device *real_dev,
					struct rmnet_port *port)
{
	struct rmnet_port *port = rmnet_get_port_rtnl(real_dev);

	if (port->nr_rmnet_devs)
		return -EINVAL;

@@ -52,6 +70,9 @@ static int rmnet_unregister_real_device(struct net_device *real_dev)

	kfree(port);

	/* release reference on real_dev */
	dev_put(real_dev);

	netdev_dbg(real_dev, "Removed from rmnet\n");
	return 0;
}
@@ -77,6 +98,9 @@ static int rmnet_register_real_device(struct net_device *real_dev)
		return -EBUSY;
	}

	/* hold on to real dev for MAP data */
	dev_hold(real_dev);

	for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++)
		INIT_HLIST_HEAD(&port->muxed_ep[entry]);

@@ -84,33 +108,28 @@ static int rmnet_register_real_device(struct net_device *real_dev)
	return 0;
}

static void rmnet_unregister_bridge(struct rmnet_port *port)
static void rmnet_unregister_bridge(struct net_device *dev,
				    struct rmnet_port *port)
{
	struct net_device *bridge_dev, *real_dev, *rmnet_dev;
	struct rmnet_port *real_port;
	struct rmnet_port *bridge_port;
	struct net_device *bridge_dev;

	if (port->rmnet_mode != RMNET_EPMODE_BRIDGE)
		return;

	rmnet_dev = port->rmnet_dev;
	/* bridge slave handling */
	if (!port->nr_rmnet_devs) {
		/* bridge device */
		real_dev = port->bridge_ep;
		bridge_dev = port->dev;
		bridge_dev = port->bridge_ep;

		real_port = rmnet_get_port_rtnl(real_dev);
		real_port->bridge_ep = NULL;
		real_port->rmnet_mode = RMNET_EPMODE_VND;
		bridge_port = rmnet_get_port_rtnl(bridge_dev);
		bridge_port->bridge_ep = NULL;
		bridge_port->rmnet_mode = RMNET_EPMODE_VND;
	} else {
		/* real device */
		bridge_dev = port->bridge_ep;

		port->bridge_ep = NULL;
		port->rmnet_mode = RMNET_EPMODE_VND;
		bridge_port = rmnet_get_port_rtnl(bridge_dev);
		rmnet_unregister_real_device(bridge_dev, bridge_port);
	}

	netdev_upper_dev_unlink(bridge_dev, rmnet_dev);
	rmnet_unregister_real_device(bridge_dev);
}

static int rmnet_newlink(struct net *src_net, struct net_device *dev,
@@ -125,11 +144,6 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
	int err = 0;
	u16 mux_id;

	if (!tb[IFLA_LINK]) {
		NL_SET_ERR_MSG_MOD(extack, "link not specified");
		return -EINVAL;
	}

	real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
	if (!real_dev || !dev)
		return -ENODEV;
@@ -152,12 +166,7 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
	if (err)
		goto err1;

	err = netdev_upper_dev_link(real_dev, dev, extack);
	if (err < 0)
		goto err2;

	port->rmnet_mode = mode;
	port->rmnet_dev = dev;

	hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);

@@ -173,11 +182,8 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,

	return 0;

err2:
	unregister_netdevice(dev);
	rmnet_vnd_dellink(mux_id, port, ep);
err1:
	rmnet_unregister_real_device(real_dev);
	rmnet_unregister_real_device(real_dev, port);
err0:
	kfree(ep);
	return err;
@@ -186,74 +192,77 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
static void rmnet_dellink(struct net_device *dev, struct list_head *head)
{
	struct rmnet_priv *priv = netdev_priv(dev);
	struct net_device *real_dev, *bridge_dev;
	struct rmnet_port *real_port, *bridge_port;
	struct net_device *real_dev;
	struct rmnet_endpoint *ep;
	u8 mux_id = priv->mux_id;
	struct rmnet_port *port;
	u8 mux_id;

	real_dev = priv->real_dev;

	if (!rmnet_is_real_dev_registered(real_dev))
	if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
		return;

	real_port = rmnet_get_port_rtnl(real_dev);
	bridge_dev = real_port->bridge_ep;
	if (bridge_dev) {
		bridge_port = rmnet_get_port_rtnl(bridge_dev);
		rmnet_unregister_bridge(bridge_port);
	}
	port = rmnet_get_port_rtnl(real_dev);

	ep = rmnet_get_endpoint(real_port, mux_id);
	mux_id = rmnet_vnd_get_mux(dev);

	ep = rmnet_get_endpoint(port, mux_id);
	if (ep) {
		hlist_del_init_rcu(&ep->hlnode);
		rmnet_vnd_dellink(mux_id, real_port, ep);
		rmnet_unregister_bridge(dev, port);
		rmnet_vnd_dellink(mux_id, port, ep);
		kfree(ep);
	}
	rmnet_unregister_real_device(real_dev, port);

	netdev_upper_dev_unlink(real_dev, dev);
	rmnet_unregister_real_device(real_dev);
	unregister_netdevice_queue(dev, head);
}

static void rmnet_force_unassociate_device(struct net_device *real_dev)
static void rmnet_force_unassociate_device(struct net_device *dev)
{
	struct net_device *real_dev = dev;
	struct hlist_node *tmp_ep;
	struct rmnet_endpoint *ep;
	struct rmnet_port *port;
	unsigned long bkt_ep;
	LIST_HEAD(list);

	port = rmnet_get_port_rtnl(real_dev);
	if (!rmnet_is_real_dev_registered(real_dev))
		return;

	ASSERT_RTNL();

	port = rmnet_get_port_rtnl(dev);

	rcu_read_lock();
	rmnet_unregister_bridge(dev, port);

	if (port->nr_rmnet_devs) {
		/* real device */
		rmnet_unregister_bridge(port);
	hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
		unregister_netdevice_queue(ep->egress_dev, &list);
			netdev_upper_dev_unlink(real_dev, ep->egress_dev);
		rmnet_vnd_dellink(ep->mux_id, port, ep);

		hlist_del_init_rcu(&ep->hlnode);
		kfree(ep);
	}
		rmnet_unregister_real_device(real_dev);

	rcu_read_unlock();
	unregister_netdevice_many(&list);
	} else {
		rmnet_unregister_bridge(port);
	}

	rmnet_unregister_real_device(real_dev, port);
}

static int rmnet_config_notify_cb(struct notifier_block *nb,
				  unsigned long event, void *data)
{
	struct net_device *real_dev = netdev_notifier_info_to_dev(data);
	struct net_device *dev = netdev_notifier_info_to_dev(data);

	if (!rmnet_is_real_dev_registered(real_dev))
	if (!dev)
		return NOTIFY_DONE;

	switch (event) {
	case NETDEV_UNREGISTER:
		netdev_dbg(real_dev, "Kernel unregister\n");
		rmnet_force_unassociate_device(real_dev);
		netdev_dbg(dev, "Kernel unregister\n");
		rmnet_force_unassociate_device(dev);
		break;

	default:
@@ -295,18 +304,16 @@ static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[],
	if (!dev)
		return -ENODEV;

	real_dev = priv->real_dev;
	if (!rmnet_is_real_dev_registered(real_dev))
	real_dev = __dev_get_by_index(dev_net(dev),
				      nla_get_u32(tb[IFLA_LINK]));

	if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
		return -ENODEV;

	port = rmnet_get_port_rtnl(real_dev);

	if (data[IFLA_RMNET_MUX_ID]) {
		mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]);
		if (rmnet_get_endpoint(port, mux_id)) {
			NL_SET_ERR_MSG_MOD(extack, "MUX ID already exists");
			return -EINVAL;
		}
		ep = rmnet_get_endpoint(port, priv->mux_id);
		if (!ep)
			return -ENODEV;
@@ -381,10 +388,11 @@ struct rtnl_link_ops rmnet_link_ops __read_mostly = {
	.fill_info	= rmnet_fill_info,
};

struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev)
/* Needs either rcu_read_lock() or rtnl lock */
struct rmnet_port *rmnet_get_port(struct net_device *real_dev)
{
	if (rmnet_is_real_dev_registered(real_dev))
		return rcu_dereference_bh(real_dev->rx_handler_data);
		return rcu_dereference_rtnl(real_dev->rx_handler_data);
	else
		return NULL;
}
@@ -410,7 +418,7 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
	struct rmnet_port *port, *slave_port;
	int err;

	port = rmnet_get_port_rtnl(real_dev);
	port = rmnet_get_port(real_dev);

	/* If there is more than one rmnet dev attached, its probably being
	 * used for muxing. Skip the briding in that case
@@ -418,9 +426,6 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
	if (port->nr_rmnet_devs > 1)
		return -EINVAL;

	if (port->rmnet_mode != RMNET_EPMODE_VND)
		return -EINVAL;

	if (rmnet_is_real_dev_registered(slave_dev))
		return -EBUSY;

@@ -428,17 +433,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
	if (err)
		return -EBUSY;

	err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL,
					   extack);
	if (err) {
		rmnet_unregister_real_device(slave_dev);
		return err;
	}

	slave_port = rmnet_get_port_rtnl(slave_dev);
	slave_port = rmnet_get_port(slave_dev);
	slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE;
	slave_port->bridge_ep = real_dev;
	slave_port->rmnet_dev = rmnet_dev;

	port->rmnet_mode = RMNET_EPMODE_BRIDGE;
	port->bridge_ep = slave_dev;
@@ -450,9 +447,16 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
int rmnet_del_bridge(struct net_device *rmnet_dev,
		     struct net_device *slave_dev)
{
	struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev);
	struct rmnet_priv *priv = netdev_priv(rmnet_dev);
	struct net_device *real_dev = priv->real_dev;
	struct rmnet_port *port, *slave_port;

	rmnet_unregister_bridge(port);
	port = rmnet_get_port(real_dev);
	port->rmnet_mode = RMNET_EPMODE_VND;
	port->bridge_ep = NULL;

	slave_port = rmnet_get_port(slave_dev);
	rmnet_unregister_real_device(slave_dev, slave_port);

	netdev_dbg(slave_dev, "removed from rmnet as slave\n");
	return 0;
@@ -478,8 +482,8 @@ static int __init rmnet_init(void)

static void __exit rmnet_exit(void)
{
	rtnl_link_unregister(&rmnet_link_ops);
	unregister_netdevice_notifier(&rmnet_dev_notifier);
	rtnl_link_unregister(&rmnet_link_ops);
}

module_init(rmnet_init)
+1 −2
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ struct rmnet_port {
	u8 rmnet_mode;
	struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP];
	struct net_device *bridge_ep;
	struct net_device *rmnet_dev;
};

extern struct rtnl_link_ops rmnet_link_ops;
@@ -75,7 +74,7 @@ struct rmnet_priv {
	struct rmnet_priv_stats stats;
};

struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev);
struct rmnet_port *rmnet_get_port(struct net_device *real_dev);
struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id);
int rmnet_add_bridge(struct net_device *rmnet_dev,
		     struct net_device *slave_dev,
+2 −5
Original line number Diff line number Diff line
@@ -168,9 +168,6 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
static void
rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev)
{
	if (skb_mac_header_was_set(skb))
		skb_push(skb, skb->mac_len);

	if (bridge_dev) {
		skb->dev = bridge_dev;
		dev_queue_xmit(skb);
@@ -196,7 +193,7 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb)
		return RX_HANDLER_PASS;

	dev = skb->dev;
	port = rmnet_get_port_rcu(dev);
	port = rmnet_get_port(dev);

	switch (port->rmnet_mode) {
	case RMNET_EPMODE_VND:
@@ -229,7 +226,7 @@ void rmnet_egress_handler(struct sk_buff *skb)
	skb->dev = priv->real_dev;
	mux_id = priv->mux_id;

	port = rmnet_get_port_rcu(skb->dev);
	port = rmnet_get_port(skb->dev);
	if (!port)
		goto drop;

+8 −0
Original line number Diff line number Diff line
@@ -276,6 +276,14 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port,
	return 0;
}

u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev)
{
	struct rmnet_priv *priv;

	priv = netdev_priv(rmnet_dev);
	return priv->mux_id;
}

int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable)
{
	netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable);
+1 −0
Original line number Diff line number Diff line
@@ -25,5 +25,6 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port,
		      struct rmnet_endpoint *ep);
void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev);
void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev);
u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev);
void rmnet_vnd_setup(struct net_device *dev);
#endif /* _RMNET_VND_H_ */
Loading