RDMA/core: Add support to set privileged QKEY parameter
authorPatrisious Haddad <phaddad@nvidia.com>
Mon, 9 Oct 2023 10:43:58 +0000 (13:43 +0300)
committerLeon Romanovsky <leon@kernel.org>
Thu, 19 Oct 2023 06:31:00 +0000 (09:31 +0300)
Add netlink command that enables/disables privileged QKEY by default.

It is disabled by default, since according to IB spec only privileged
users are allowed to use privileged QKEY.
According to the IB specification rel-1.6, section 3.5.3:
"QKEYs with the most significant bit set are considered controlled
QKEYs, and a HCA does not allow a consumer to arbitrarily specify a
controlled QKEY."

Using rdma tool,
$rdma system set privileged-qkey on

When enabled non-privileged users would be able to use
controlled QKEYs which are considered privileged.

Using rdma tool,
$rdma system set privileged-qkey off

When disabled only privileged users would be able to use
controlled QKEYs.

You can also use the command below to check the parameter state:
$rdma system show
netns shared privileged-qkey off copy-on-fork on

Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
Link: https://lore.kernel.org/r/90398be70a9d23d2aa9d0f9fd11d2c264c1be534.1696848201.git.leon@kernel.org
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/nldev.c
drivers/infiniband/core/uverbs_cmd.c
include/uapi/rdma/rdma_netlink.h

index f66f48d860ec3817a7c64f954dae0e92eef6fd8c..dd7715ba9fd15eb75cea0dec32aa018950561131 100644 (file)
@@ -373,4 +373,5 @@ void rdma_umap_priv_init(struct rdma_umap_priv *priv,
 
 void ib_cq_pool_cleanup(struct ib_device *dev);
 
+bool rdma_nl_get_privileged_qkey(void);
 #endif /* _CORE_PRIV_H */
index 456545007c14c446d3802e650083e28259a27677..5c805fa6187f9878eee57d3f0bae178ad59974a1 100644 (file)
 #include "restrack.h"
 #include "uverbs.h"
 
+/*
+ * This determines whether a non-privileged user is allowed to specify a
+ * controlled QKEY or not, when true non-privileged user is allowed to specify
+ * a controlled QKEY.
+ */
+static bool privileged_qkey;
+
 typedef int (*res_fill_func_t)(struct sk_buff*, bool,
                               struct rdma_restrack_entry*, uint32_t);
 
@@ -156,6 +163,7 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
        [RDMA_NLDEV_SYS_ATTR_COPY_ON_FORK]      = { .type = NLA_U8 },
        [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX]  = { .type = NLA_U32 },
        [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC] = { .type = NLA_U8 },
+       [RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE] = { .type = NLA_U8 },
 };
 
 static int put_driver_name_print_type(struct sk_buff *msg, const char *name,
@@ -237,6 +245,12 @@ int rdma_nl_put_driver_u64_hex(struct sk_buff *msg, const char *name, u64 value)
 }
 EXPORT_SYMBOL(rdma_nl_put_driver_u64_hex);
 
+bool rdma_nl_get_privileged_qkey(void)
+{
+       return privileged_qkey || capable(CAP_NET_RAW);
+}
+EXPORT_SYMBOL(rdma_nl_get_privileged_qkey);
+
 static int fill_nldev_handle(struct sk_buff *msg, struct ib_device *device)
 {
        if (nla_put_u32(msg, RDMA_NLDEV_ATTR_DEV_INDEX, device->index))
@@ -1901,6 +1915,12 @@ static int nldev_sys_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
                return err;
        }
 
+       err = nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE,
+                        (u8)privileged_qkey);
+       if (err) {
+               nlmsg_free(msg);
+               return err;
+       }
        /*
         * Copy-on-fork is supported.
         * See commits:
@@ -1917,18 +1937,11 @@ static int nldev_sys_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
        return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
 }
 
-static int nldev_set_sys_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
-                                 struct netlink_ext_ack *extack)
+static int nldev_set_sys_set_netns_doit(struct nlattr *tb[])
 {
-       struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
        u8 enable;
        int err;
 
-       err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
-                         nldev_policy, extack);
-       if (err || !tb[RDMA_NLDEV_SYS_ATTR_NETNS_MODE])
-               return -EINVAL;
-
        enable = nla_get_u8(tb[RDMA_NLDEV_SYS_ATTR_NETNS_MODE]);
        /* Only 0 and 1 are supported */
        if (enable > 1)
@@ -1938,6 +1951,40 @@ static int nldev_set_sys_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
        return err;
 }
 
+static int nldev_set_sys_set_pqkey_doit(struct nlattr *tb[])
+{
+       u8 enable;
+
+       enable = nla_get_u8(tb[RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE]);
+       /* Only 0 and 1 are supported */
+       if (enable > 1)
+               return -EINVAL;
+
+       privileged_qkey = enable;
+       return 0;
+}
+
+static int nldev_set_sys_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
+                                 struct netlink_ext_ack *extack)
+{
+       struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
+       int err;
+
+       err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
+                         nldev_policy, extack);
+       if (err)
+               return -EINVAL;
+
+       if (tb[RDMA_NLDEV_SYS_ATTR_NETNS_MODE])
+               return nldev_set_sys_set_netns_doit(tb);
+
+       if (tb[RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE])
+               return nldev_set_sys_set_pqkey_doit(tb);
+
+       return -EINVAL;
+}
+
+
 static int nldev_stat_set_mode_doit(struct sk_buff *msg,
                                    struct netlink_ext_ack *extack,
                                    struct nlattr *tb[],
index e836c9c477f6755e97a469b5f0cf588d8c1aa21c..6de05ade2ba94c213fd906c1703889ba83615d75 100644 (file)
@@ -1851,7 +1851,8 @@ static int modify_qp(struct uverbs_attr_bundle *attrs,
        if (cmd->base.attr_mask & IB_QP_PATH_MIG_STATE)
                attr->path_mig_state = cmd->base.path_mig_state;
        if (cmd->base.attr_mask & IB_QP_QKEY) {
-               if (cmd->base.qkey & IB_QP_SET_QKEY && !capable(CAP_NET_RAW)) {
+               if (cmd->base.qkey & IB_QP_SET_QKEY &&
+                   !rdma_nl_get_privileged_qkey()) {
                        ret = -EPERM;
                        goto release_qp;
                }
index 2830695c355625c401cdd30b273d1814bde7b7f0..723bbb0f7042172f45598e8670c58ad79a40cfd2 100644 (file)
@@ -556,6 +556,8 @@ enum rdma_nldev_attr {
        RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX,   /* u32 */
        RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC, /* u8 */
 
+       RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE, /* u8 */
+
        /*
         * Always the end
         */