},
{
.cmd = PSP_CMD_DEV_SET,
- .pre_doit = psp_device_get_locked,
+ .pre_doit = psp_device_get_locked_admin,
.doit = psp_nl_dev_set_doit,
.post_doit = psp_device_unlock,
.policy = psp_dev_set_nl_policy,
},
{
.cmd = PSP_CMD_KEY_ROTATE,
- .pre_doit = psp_device_get_locked,
+ .pre_doit = psp_device_get_locked_admin,
.doit = psp_nl_key_rotate_doit,
.post_doit = psp_device_unlock,
.policy = psp_key_rotate_nl_policy,
* psp_dev_check_access() - check if user in a given net ns can access PSP dev
* @psd: PSP device structure user is trying to access
* @net: net namespace user is in
+ * @admin: If true, only allow access from @psd's main device's netns,
+ * for admin operations like config changes and key rotation.
+ * If false, also allow access from network namespaces that have
+ * an associated device with @psd, for read-only and association
+ * management operations.
*
* Return: 0 if PSP device should be visible in @net, errno otherwise.
*/
-int psp_dev_check_access(struct psp_dev *psd, struct net *net)
+int psp_dev_check_access(struct psp_dev *psd, struct net *net, bool admin)
{
if (dev_net(psd->main_netdev) == net)
return 0;
/* Device stuff */
static struct psp_dev *
-psp_device_get_and_lock(struct net *net, struct nlattr *dev_id)
+psp_device_get_and_lock(struct net *net, struct nlattr *dev_id,
+ bool admin)
{
struct psp_dev *psd;
int err;
mutex_lock(&psd->lock);
mutex_unlock(&psp_devs_lock);
- err = psp_dev_check_access(psd, net);
+ err = psp_dev_check_access(psd, net, admin);
if (err) {
mutex_unlock(&psd->lock);
return ERR_PTR(err);
return psd;
}
-int psp_device_get_locked(const struct genl_split_ops *ops,
- struct sk_buff *skb, struct genl_info *info)
+static int __psp_device_get_locked(const struct genl_split_ops *ops,
+ struct sk_buff *skb, struct genl_info *info,
+ bool admin)
{
if (GENL_REQ_ATTR_CHECK(info, PSP_A_DEV_ID))
return -EINVAL;
info->user_ptr[0] = psp_device_get_and_lock(genl_info_net(info),
- info->attrs[PSP_A_DEV_ID]);
+ info->attrs[PSP_A_DEV_ID],
+ admin);
return PTR_ERR_OR_ZERO(info->user_ptr[0]);
}
+int psp_device_get_locked_admin(const struct genl_split_ops *ops,
+ struct sk_buff *skb, struct genl_info *info)
+{
+ return __psp_device_get_locked(ops, skb, info, true);
+}
+
+int psp_device_get_locked(const struct genl_split_ops *ops,
+ struct sk_buff *skb, struct genl_info *info)
+{
+ return __psp_device_get_locked(ops, skb, info, false);
+}
+
void
psp_device_unlock(const struct genl_split_ops *ops, struct sk_buff *skb,
struct genl_info *info)
psp_nl_dev_get_dumpit_one(struct sk_buff *rsp, struct netlink_callback *cb,
struct psp_dev *psd)
{
- if (psp_dev_check_access(psd, sock_net(rsp->sk)))
+ if (psp_dev_check_access(psd, sock_net(rsp->sk), false))
return 0;
return psp_nl_dev_fill(psd, rsp, genl_info_dump(cb));
*/
mutex_lock(&psd->lock);
if (!psp_dev_is_registered(psd) ||
- psp_dev_check_access(psd, genl_info_net(info))) {
+ psp_dev_check_access(psd, genl_info_net(info), false)) {
mutex_unlock(&psd->lock);
psp_dev_put(psd);
psd = NULL;
psp_dev_put(psd);
} else {
- psd = psp_device_get_and_lock(genl_info_net(info), id);
+ psd = psp_device_get_and_lock(genl_info_net(info), id, false);
if (IS_ERR(psd)) {
err = PTR_ERR(psd);
goto err_sock_put;
psp_nl_stats_get_dumpit_one(struct sk_buff *rsp, struct netlink_callback *cb,
struct psp_dev *psd)
{
- if (psp_dev_check_access(psd, sock_net(rsp->sk)))
+ if (psp_dev_check_access(psd, sock_net(rsp->sk), false))
return 0;
return psp_nl_stats_fill(psd, rsp, genl_info_dump(cb));