IB/mlx5: Enable DEVX white list commands
authorYishai Hadas <yishaih@mellanox.com>
Thu, 20 Sep 2018 18:45:20 +0000 (21:45 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Thu, 27 Sep 2018 19:01:33 +0000 (13:01 -0600)
Enable DEVX white list commands without the need for CAP_NET_RAW.

DEVX uid must exist from the ucontext or the device so that the firmware
will mask unprivileged capabilities.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/hw/mlx5/devx.c

index 97cac57dcb3dde91c6345463b998b356eecde3c1..c11640047f26818bb44c831126537c9653ce206c 100644 (file)
@@ -61,9 +61,6 @@ int mlx5_ib_devx_create(struct mlx5_ib_dev *dev)
            !(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_UMEM))
                return -EINVAL;
 
-       if (!capable(CAP_NET_RAW))
-               return -EPERM;
-
        MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
        MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type, MLX5_OBJ_TYPE_UCTX);
 
@@ -476,12 +473,49 @@ static bool devx_is_obj_query_cmd(const void *in)
        }
 }
 
+static bool devx_is_whitelist_cmd(void *in)
+{
+       u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
+
+       switch (opcode) {
+       case MLX5_CMD_OP_QUERY_HCA_CAP:
+       case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in)
+{
+       if (devx_is_whitelist_cmd(cmd_in)) {
+               struct mlx5_ib_dev *dev;
+
+               if (c->devx_uid)
+                       return c->devx_uid;
+
+               dev = to_mdev(c->ibucontext.device);
+               if (dev->devx_whitelist_uid)
+                       return dev->devx_whitelist_uid;
+
+               return -EOPNOTSUPP;
+       }
+
+       if (!c->devx_uid)
+               return -EINVAL;
+
+       if (!capable(CAP_NET_RAW))
+               return -EPERM;
+
+       return c->devx_uid;
+}
 static bool devx_is_general_cmd(void *in)
 {
        u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
 
        switch (opcode) {
        case MLX5_CMD_OP_QUERY_HCA_CAP:
+       case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
        case MLX5_CMD_OP_QUERY_VPORT_STATE:
        case MLX5_CMD_OP_QUERY_ADAPTER:
        case MLX5_CMD_OP_QUERY_ISSI:
@@ -589,14 +623,16 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
                                        MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
        void *cmd_out;
        int err;
+       int uid;
 
        c = devx_ufile2uctx(file);
        if (IS_ERR(c))
                return PTR_ERR(c);
        dev = to_mdev(c->ibucontext.device);
 
-       if (!c->devx_uid)
-               return -EPERM;
+       uid = devx_get_uid(c, cmd_in);
+       if (uid < 0)
+               return uid;
 
        /* Only white list of some general HCA commands are allowed for this method. */
        if (!devx_is_general_cmd(cmd_in))
@@ -606,7 +642,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
        if (IS_ERR(cmd_out))
                return PTR_ERR(cmd_out);
 
-       MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
+       MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
        err = mlx5_cmd_exec(dev->mdev, cmd_in,
                            uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
                            cmd_out, cmd_out_len);
@@ -816,9 +852,11 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
        struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
        struct devx_obj *obj;
        int err;
+       int uid;
 
-       if (!c->devx_uid)
-               return -EPERM;
+       uid = devx_get_uid(c, cmd_in);
+       if (uid < 0)
+               return uid;
 
        if (!devx_is_obj_create_cmd(cmd_in))
                return -EINVAL;
@@ -831,7 +869,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
        if (!obj)
                return -ENOMEM;
 
-       MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
+       MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
        devx_set_umem_valid(cmd_in);
 
        err = mlx5_cmd_exec(dev->mdev, cmd_in,
@@ -868,9 +906,11 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
        struct devx_obj *obj = uobj->object;
        void *cmd_out;
        int err;
+       int uid;
 
-       if (!c->devx_uid)
-               return -EPERM;
+       uid = devx_get_uid(c, cmd_in);
+       if (uid < 0)
+               return uid;
 
        if (!devx_is_obj_modify_cmd(cmd_in))
                return -EINVAL;
@@ -882,7 +922,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
        if (IS_ERR(cmd_out))
                return PTR_ERR(cmd_out);
 
-       MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
+       MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
        devx_set_umem_valid(cmd_in);
 
        err = mlx5_cmd_exec(obj->mdev, cmd_in,
@@ -907,9 +947,11 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
        struct devx_obj *obj = uobj->object;
        void *cmd_out;
        int err;
+       int uid;
 
-       if (!c->devx_uid)
-               return -EPERM;
+       uid = devx_get_uid(c, cmd_in);
+       if (uid < 0)
+               return uid;
 
        if (!devx_is_obj_query_cmd(cmd_in))
                return -EINVAL;
@@ -921,7 +963,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
        if (IS_ERR(cmd_out))
                return PTR_ERR(cmd_out);
 
-       MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
+       MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
        err = mlx5_cmd_exec(obj->mdev, cmd_in,
                            uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
                            cmd_out, cmd_out_len);
@@ -1020,6 +1062,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(
        int err;
 
        if (!c->devx_uid)
+               return -EINVAL;
+
+       if (!capable(CAP_NET_RAW))
                return -EPERM;
 
        obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);