Skip to content

Commit

Permalink
IB/hfi: Properly set permissions for user device files
Browse files Browse the repository at this point in the history
Some of the device files are required to be user accessible for PSM while
most should remain accessible only by root.

Add a parameter to hfi1_cdev_init which controls if the user should have access
to this device which places it in a different class with the appropriate
devnode callback.

In addition set the devnode call back for the existing class to be a bit more
explicit for those permissions.

Finally remove the unnecessary null check before class_destroy

Tested-by: Donald Dutile <[email protected]>
Signed-off-by: Haralanov, Mitko ([email protected])
Signed-off-by: Ira Weiny <[email protected]>
Signed-off-by: Doug Ledford <[email protected]>
  • Loading branch information
weiny2 authored and dledford committed Sep 18, 2015
1 parent 7d63046 commit e116a64
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 12 deletions.
54 changes: 48 additions & 6 deletions drivers/staging/rdma/hfi1/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@
#include "device.h"

static struct class *class;
static struct class *user_class;
static dev_t hfi1_dev;

int hfi1_cdev_init(int minor, const char *name,
const struct file_operations *fops,
struct cdev *cdev, struct device **devp)
struct cdev *cdev, struct device **devp,
bool user_accessible)
{
const dev_t dev = MKDEV(MAJOR(hfi1_dev), minor);
struct device *device = NULL;
Expand All @@ -78,7 +80,11 @@ int hfi1_cdev_init(int minor, const char *name,
goto done;
}

device = device_create(class, NULL, dev, NULL, "%s", name);
if (user_accessible)
device = device_create(user_class, NULL, dev, NULL, "%s", name);
else
device = device_create(class, NULL, dev, NULL, "%s", name);

if (!IS_ERR(device))
goto done;
ret = PTR_ERR(device);
Expand Down Expand Up @@ -110,6 +116,26 @@ const char *class_name(void)
return hfi1_class_name;
}

static char *hfi1_devnode(struct device *dev, umode_t *mode)
{
if (mode)
*mode = 0600;
return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
}

static const char *hfi1_class_name_user = "hfi1_user";
const char *class_name_user(void)
{
return hfi1_class_name_user;
}

static char *hfi1_user_devnode(struct device *dev, umode_t *mode)
{
if (mode)
*mode = 0666;
return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
}

int __init dev_init(void)
{
int ret;
Expand All @@ -125,18 +151,34 @@ int __init dev_init(void)
ret = PTR_ERR(class);
pr_err("Could not create device class (err %d)\n", -ret);
unregister_chrdev_region(hfi1_dev, HFI1_NMINORS);
goto done;
}
class->devnode = hfi1_devnode;

user_class = class_create(THIS_MODULE, class_name_user());
if (IS_ERR(user_class)) {
ret = PTR_ERR(user_class);
pr_err("Could not create device class for user accessible files (err %d)\n",
-ret);
class_destroy(class);
class = NULL;
user_class = NULL;
unregister_chrdev_region(hfi1_dev, HFI1_NMINORS);
goto done;
}
user_class->devnode = hfi1_user_devnode;

done:
return ret;
}

void dev_cleanup(void)
{
if (class) {
class_destroy(class);
class = NULL;
}
class_destroy(class);
class = NULL;

class_destroy(user_class);
user_class = NULL;

unregister_chrdev_region(hfi1_dev, HFI1_NMINORS);
}
3 changes: 2 additions & 1 deletion drivers/staging/rdma/hfi1/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@

int hfi1_cdev_init(int minor, const char *name,
const struct file_operations *fops,
struct cdev *cdev, struct device **devp);
struct cdev *cdev, struct device **devp,
bool user_accessible);
void hfi1_cdev_cleanup(struct cdev *cdev, struct device **devp);
const char *class_name(void);
int __init dev_init(void);
Expand Down
5 changes: 3 additions & 2 deletions drivers/staging/rdma/hfi1/diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ int hfi1_diag_add(struct hfi1_devdata *dd)
if (atomic_inc_return(&diagpkt_count) == 1) {
ret = hfi1_cdev_init(HFI1_DIAGPKT_MINOR, name,
&diagpkt_file_ops, &diagpkt_cdev,
&diagpkt_device);
&diagpkt_device, false);
}

return ret;
Expand Down Expand Up @@ -592,7 +592,8 @@ static int hfi1_snoop_add(struct hfi1_devdata *dd, const char *name)

ret = hfi1_cdev_init(HFI1_SNOOP_CAPTURE_BASE + dd->unit, name,
&snoop_file_ops,
&dd->hfi1_snoop.cdev, &dd->hfi1_snoop.class_dev);
&dd->hfi1_snoop.cdev, &dd->hfi1_snoop.class_dev,
false);

if (ret) {
dd_dev_err(dd, "Couldn't create %s device: %d", name, ret);
Expand Down
9 changes: 6 additions & 3 deletions drivers/staging/rdma/hfi1/file_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -2090,22 +2090,25 @@ static int user_add(struct hfi1_devdata *dd)

if (atomic_inc_return(&user_count) == 1) {
ret = hfi1_cdev_init(0, class_name(), &hfi1_file_ops,
&wildcard_cdev, &wildcard_device);
&wildcard_cdev, &wildcard_device,
true);
if (ret)
goto done;
}

snprintf(name, sizeof(name), "%s_%d", class_name(), dd->unit);
ret = hfi1_cdev_init(dd->unit + 1, name, &hfi1_file_ops,
&dd->user_cdev, &dd->user_device);
&dd->user_cdev, &dd->user_device,
true);
if (ret)
goto done;

if (create_ui) {
snprintf(name, sizeof(name),
"%s_ui%d", class_name(), dd->unit);
ret = hfi1_cdev_init(dd->unit + UI_OFFSET, name, &ui_file_ops,
&dd->ui_cdev, &dd->ui_device);
&dd->ui_cdev, &dd->ui_device,
false);
if (ret)
goto done;
}
Expand Down

0 comments on commit e116a64

Please sign in to comment.