From: Jiri Pirko <j...@mellanox.com>

Add simple block get operation which primary purpose is to check the
block existence by block index.

Signed-off-by: Jiri Pirko <j...@mellanox.com>
---
v6->v7:
- new patch
---
 include/uapi/linux/rtnetlink.h |  6 ++++
 net/sched/cls_api.c            | 64 ++++++++++++++++++++++++++++++++++++++++++
 security/selinux/nlmsgtab.c    |  5 +++-
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 9c026d9..038cde7 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -150,6 +150,12 @@ enum {
        RTM_NEWCACHEREPORT = 96,
 #define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
 
+       RTM_NEWBLOCK = 100,
+#define RTM_NEWBLOCK RTM_NEWBLOCK
+       RTM_DELBLOCK,
+#define RTM_DELBLOCK RTM_DELBLOCK
+       RTM_GETBLOCK,
+#define RTM_GETBLOCK RTM_GETBLOCK
        __RTM_MAX,
 #define RTM_MAX                (((__RTM_MAX + 3) & ~3) - 1)
 };
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index d687e58..14e4f20 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1553,6 +1553,69 @@ int tc_setup_cb_call(struct tcf_block *block, struct 
tcf_exts *exts,
 }
 EXPORT_SYMBOL(tc_setup_cb_call);
 
+static int block_notify_fill(struct net *net, struct sk_buff *skb,
+                            struct tcf_block *block, u32 portid, u32 seq,
+                            u16 flags, int event)
+{
+       struct nlmsghdr *nlh;
+       struct tcmsg *tcm;
+
+       nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags);
+       if (!nlh)
+               return -EMSGSIZE;
+       tcm = nlmsg_data(nlh);
+       memset(tcm, 0, sizeof(*tcm));
+       tcm->tcm_family = AF_UNSPEC;
+       tcm->tcm_ifindex = TCM_IFINDEX_MAGIC_BLOCK;
+       tcm->tcm_block_index = block->index;
+       return 0;
+}
+
+static int block_notify(struct net *net, struct sk_buff *oskb,
+                       struct nlmsghdr *n, struct tcf_block *block, int event)
+{
+       u32 portid = NETLINK_CB(oskb).portid;
+       struct sk_buff *skb;
+       int err;
+
+       skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+       if (!skb)
+               return -ENOBUFS;
+
+       err = block_notify_fill(net, skb, block, portid,
+                               n->nlmsg_seq, n->nlmsg_flags, event);
+       if (err) {
+               kfree_skb(skb);
+               return err;
+       }
+
+       return netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT);
+}
+
+static int tc_ctl_block(struct sk_buff *skb, struct nlmsghdr *n,
+                       struct netlink_ext_ack *extack)
+{
+       struct net *net = sock_net(skb->sk);
+       struct tcf_block *block;
+       struct tcmsg *tcm;
+
+       if (n->nlmsg_len < nlmsg_msg_size(sizeof(*tcm)))
+               return -EINVAL;
+
+       tcm = nlmsg_data(n);
+
+       if (tcm->tcm_ifindex != TCM_IFINDEX_MAGIC_BLOCK)
+               return -EINVAL;
+
+       block = tcf_block_lookup(net, tcm->tcm_block_index);
+       if (!block) {
+               NL_SET_ERR_MSG(extack, "Block with the given index does not 
exist");
+               return -EINVAL;
+       }
+
+       return block_notify(net, skb, n, block, RTM_NEWBLOCK);
+}
+
 static __net_init int tcf_net_init(struct net *net)
 {
        struct tcf_net *tn = net_generic(net, tcf_net_id);
@@ -1591,6 +1654,7 @@ static int __init tc_filter_init(void)
        rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL, 0);
        rtnl_register(PF_UNSPEC, RTM_GETTFILTER, tc_ctl_tfilter,
                      tc_dump_tfilter, 0);
+       rtnl_register(PF_UNSPEC, RTM_GETBLOCK, tc_ctl_block, NULL, 0);
 
        return 0;
 }
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 7b7433a..4e95a46 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -80,6 +80,9 @@ static const struct nlmsg_perm nlmsg_route_perms[] =
        { RTM_NEWSTATS,         NETLINK_ROUTE_SOCKET__NLMSG_READ },
        { RTM_GETSTATS,         NETLINK_ROUTE_SOCKET__NLMSG_READ  },
        { RTM_NEWCACHEREPORT,   NETLINK_ROUTE_SOCKET__NLMSG_READ },
+       { RTM_NEWBLOCK,         NETLINK_ROUTE_SOCKET__NLMSG_READ },
+       { RTM_DELBLOCK,         NETLINK_ROUTE_SOCKET__NLMSG_READ },
+       { RTM_GETBLOCK,         NETLINK_ROUTE_SOCKET__NLMSG_READ },
 };
 
 static const struct nlmsg_perm nlmsg_tcpdiag_perms[] =
@@ -159,7 +162,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 
*perm)
        switch (sclass) {
        case SECCLASS_NETLINK_ROUTE_SOCKET:
                /* RTM_MAX always point to RTM_SETxxxx, ie RTM_NEWxxx + 3 */
-               BUILD_BUG_ON(RTM_MAX != (RTM_NEWCACHEREPORT + 3));
+               BUILD_BUG_ON(RTM_MAX != (RTM_NEWBLOCK + 3));
                err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
                                 sizeof(nlmsg_route_perms));
                break;
-- 
2.9.5

Reply via email to