diff options
| author | Ira Weiny <ira.weiny@intel.com> | 2015-09-17 13:47:49 -0400 |
|---|---|---|
| committer | Doug Ledford <dledford@redhat.com> | 2015-09-18 11:28:47 -0400 |
| commit | e116a64fab650aed3d7b9b4db0b59c07f361bc9f (patch) | |
| tree | 87443bf22b75104c7a707e538c3ec4f5565d1a6f | |
| parent | 7d630467d7c454d801d72b58f242c373a64e39ed (diff) | |
IB/hfi: Properly set permissions for user device files
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 <ddutile@redhat.com>
Signed-off-by: Haralanov, Mitko (mitko.haralanov@intel.com)
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
| -rw-r--r-- | drivers/staging/rdma/hfi1/device.c | 54 | ||||
| -rw-r--r-- | drivers/staging/rdma/hfi1/device.h | 3 | ||||
| -rw-r--r-- | drivers/staging/rdma/hfi1/diag.c | 5 | ||||
| -rw-r--r-- | drivers/staging/rdma/hfi1/file_ops.c | 9 |
4 files changed, 59 insertions, 12 deletions
diff --git a/drivers/staging/rdma/hfi1/device.c b/drivers/staging/rdma/hfi1/device.c index 07c87a87775f..bc26a5392712 100644 --- a/drivers/staging/rdma/hfi1/device.c +++ b/drivers/staging/rdma/hfi1/device.c | |||
| @@ -57,11 +57,13 @@ | |||
| 57 | #include "device.h" | 57 | #include "device.h" |
| 58 | 58 | ||
| 59 | static struct class *class; | 59 | static struct class *class; |
| 60 | static struct class *user_class; | ||
| 60 | static dev_t hfi1_dev; | 61 | static dev_t hfi1_dev; |
| 61 | 62 | ||
| 62 | int hfi1_cdev_init(int minor, const char *name, | 63 | int hfi1_cdev_init(int minor, const char *name, |
| 63 | const struct file_operations *fops, | 64 | const struct file_operations *fops, |
| 64 | struct cdev *cdev, struct device **devp) | 65 | struct cdev *cdev, struct device **devp, |
| 66 | bool user_accessible) | ||
| 65 | { | 67 | { |
| 66 | const dev_t dev = MKDEV(MAJOR(hfi1_dev), minor); | 68 | const dev_t dev = MKDEV(MAJOR(hfi1_dev), minor); |
| 67 | struct device *device = NULL; | 69 | struct device *device = NULL; |
| @@ -78,7 +80,11 @@ int hfi1_cdev_init(int minor, const char *name, | |||
| 78 | goto done; | 80 | goto done; |
| 79 | } | 81 | } |
| 80 | 82 | ||
| 81 | device = device_create(class, NULL, dev, NULL, "%s", name); | 83 | if (user_accessible) |
| 84 | device = device_create(user_class, NULL, dev, NULL, "%s", name); | ||
| 85 | else | ||
| 86 | device = device_create(class, NULL, dev, NULL, "%s", name); | ||
| 87 | |||
| 82 | if (!IS_ERR(device)) | 88 | if (!IS_ERR(device)) |
| 83 | goto done; | 89 | goto done; |
| 84 | ret = PTR_ERR(device); | 90 | ret = PTR_ERR(device); |
| @@ -110,6 +116,26 @@ const char *class_name(void) | |||
| 110 | return hfi1_class_name; | 116 | return hfi1_class_name; |
| 111 | } | 117 | } |
| 112 | 118 | ||
| 119 | static char *hfi1_devnode(struct device *dev, umode_t *mode) | ||
| 120 | { | ||
| 121 | if (mode) | ||
| 122 | *mode = 0600; | ||
| 123 | return kasprintf(GFP_KERNEL, "%s", dev_name(dev)); | ||
| 124 | } | ||
| 125 | |||
| 126 | static const char *hfi1_class_name_user = "hfi1_user"; | ||
| 127 | const char *class_name_user(void) | ||
| 128 | { | ||
| 129 | return hfi1_class_name_user; | ||
| 130 | } | ||
| 131 | |||
| 132 | static char *hfi1_user_devnode(struct device *dev, umode_t *mode) | ||
| 133 | { | ||
| 134 | if (mode) | ||
| 135 | *mode = 0666; | ||
| 136 | return kasprintf(GFP_KERNEL, "%s", dev_name(dev)); | ||
| 137 | } | ||
| 138 | |||
| 113 | int __init dev_init(void) | 139 | int __init dev_init(void) |
| 114 | { | 140 | { |
| 115 | int ret; | 141 | int ret; |
| @@ -125,7 +151,22 @@ int __init dev_init(void) | |||
| 125 | ret = PTR_ERR(class); | 151 | ret = PTR_ERR(class); |
| 126 | pr_err("Could not create device class (err %d)\n", -ret); | 152 | pr_err("Could not create device class (err %d)\n", -ret); |
| 127 | unregister_chrdev_region(hfi1_dev, HFI1_NMINORS); | 153 | unregister_chrdev_region(hfi1_dev, HFI1_NMINORS); |
| 154 | goto done; | ||
| 128 | } | 155 | } |
| 156 | class->devnode = hfi1_devnode; | ||
| 157 | |||
| 158 | user_class = class_create(THIS_MODULE, class_name_user()); | ||
| 159 | if (IS_ERR(user_class)) { | ||
| 160 | ret = PTR_ERR(user_class); | ||
| 161 | pr_err("Could not create device class for user accessible files (err %d)\n", | ||
| 162 | -ret); | ||
| 163 | class_destroy(class); | ||
| 164 | class = NULL; | ||
| 165 | user_class = NULL; | ||
| 166 | unregister_chrdev_region(hfi1_dev, HFI1_NMINORS); | ||
| 167 | goto done; | ||
| 168 | } | ||
| 169 | user_class->devnode = hfi1_user_devnode; | ||
| 129 | 170 | ||
| 130 | done: | 171 | done: |
| 131 | return ret; | 172 | return ret; |
| @@ -133,10 +174,11 @@ done: | |||
| 133 | 174 | ||
| 134 | void dev_cleanup(void) | 175 | void dev_cleanup(void) |
| 135 | { | 176 | { |
| 136 | if (class) { | 177 | class_destroy(class); |
| 137 | class_destroy(class); | 178 | class = NULL; |
| 138 | class = NULL; | 179 | |
| 139 | } | 180 | class_destroy(user_class); |
| 181 | user_class = NULL; | ||
| 140 | 182 | ||
| 141 | unregister_chrdev_region(hfi1_dev, HFI1_NMINORS); | 183 | unregister_chrdev_region(hfi1_dev, HFI1_NMINORS); |
| 142 | } | 184 | } |
diff --git a/drivers/staging/rdma/hfi1/device.h b/drivers/staging/rdma/hfi1/device.h index 98caecd3d807..2850ff739d81 100644 --- a/drivers/staging/rdma/hfi1/device.h +++ b/drivers/staging/rdma/hfi1/device.h | |||
| @@ -52,7 +52,8 @@ | |||
| 52 | 52 | ||
| 53 | int hfi1_cdev_init(int minor, const char *name, | 53 | int hfi1_cdev_init(int minor, const char *name, |
| 54 | const struct file_operations *fops, | 54 | const struct file_operations *fops, |
| 55 | struct cdev *cdev, struct device **devp); | 55 | struct cdev *cdev, struct device **devp, |
| 56 | bool user_accessible); | ||
| 56 | void hfi1_cdev_cleanup(struct cdev *cdev, struct device **devp); | 57 | void hfi1_cdev_cleanup(struct cdev *cdev, struct device **devp); |
| 57 | const char *class_name(void); | 58 | const char *class_name(void); |
| 58 | int __init dev_init(void); | 59 | int __init dev_init(void); |
diff --git a/drivers/staging/rdma/hfi1/diag.c b/drivers/staging/rdma/hfi1/diag.c index ce01deea834c..3e8d5ac4c626 100644 --- a/drivers/staging/rdma/hfi1/diag.c +++ b/drivers/staging/rdma/hfi1/diag.c | |||
| @@ -292,7 +292,7 @@ int hfi1_diag_add(struct hfi1_devdata *dd) | |||
| 292 | if (atomic_inc_return(&diagpkt_count) == 1) { | 292 | if (atomic_inc_return(&diagpkt_count) == 1) { |
| 293 | ret = hfi1_cdev_init(HFI1_DIAGPKT_MINOR, name, | 293 | ret = hfi1_cdev_init(HFI1_DIAGPKT_MINOR, name, |
| 294 | &diagpkt_file_ops, &diagpkt_cdev, | 294 | &diagpkt_file_ops, &diagpkt_cdev, |
| 295 | &diagpkt_device); | 295 | &diagpkt_device, false); |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | return ret; | 298 | return ret; |
| @@ -592,7 +592,8 @@ static int hfi1_snoop_add(struct hfi1_devdata *dd, const char *name) | |||
| 592 | 592 | ||
| 593 | ret = hfi1_cdev_init(HFI1_SNOOP_CAPTURE_BASE + dd->unit, name, | 593 | ret = hfi1_cdev_init(HFI1_SNOOP_CAPTURE_BASE + dd->unit, name, |
| 594 | &snoop_file_ops, | 594 | &snoop_file_ops, |
| 595 | &dd->hfi1_snoop.cdev, &dd->hfi1_snoop.class_dev); | 595 | &dd->hfi1_snoop.cdev, &dd->hfi1_snoop.class_dev, |
| 596 | false); | ||
| 596 | 597 | ||
| 597 | if (ret) { | 598 | if (ret) { |
| 598 | dd_dev_err(dd, "Couldn't create %s device: %d", name, ret); | 599 | dd_dev_err(dd, "Couldn't create %s device: %d", name, ret); |
diff --git a/drivers/staging/rdma/hfi1/file_ops.c b/drivers/staging/rdma/hfi1/file_ops.c index 2c43ca5a379b..72d38500d8ce 100644 --- a/drivers/staging/rdma/hfi1/file_ops.c +++ b/drivers/staging/rdma/hfi1/file_ops.c | |||
| @@ -2090,14 +2090,16 @@ static int user_add(struct hfi1_devdata *dd) | |||
| 2090 | 2090 | ||
| 2091 | if (atomic_inc_return(&user_count) == 1) { | 2091 | if (atomic_inc_return(&user_count) == 1) { |
| 2092 | ret = hfi1_cdev_init(0, class_name(), &hfi1_file_ops, | 2092 | ret = hfi1_cdev_init(0, class_name(), &hfi1_file_ops, |
| 2093 | &wildcard_cdev, &wildcard_device); | 2093 | &wildcard_cdev, &wildcard_device, |
| 2094 | true); | ||
| 2094 | if (ret) | 2095 | if (ret) |
| 2095 | goto done; | 2096 | goto done; |
| 2096 | } | 2097 | } |
| 2097 | 2098 | ||
| 2098 | snprintf(name, sizeof(name), "%s_%d", class_name(), dd->unit); | 2099 | snprintf(name, sizeof(name), "%s_%d", class_name(), dd->unit); |
| 2099 | ret = hfi1_cdev_init(dd->unit + 1, name, &hfi1_file_ops, | 2100 | ret = hfi1_cdev_init(dd->unit + 1, name, &hfi1_file_ops, |
| 2100 | &dd->user_cdev, &dd->user_device); | 2101 | &dd->user_cdev, &dd->user_device, |
| 2102 | true); | ||
| 2101 | if (ret) | 2103 | if (ret) |
| 2102 | goto done; | 2104 | goto done; |
| 2103 | 2105 | ||
| @@ -2105,7 +2107,8 @@ static int user_add(struct hfi1_devdata *dd) | |||
| 2105 | snprintf(name, sizeof(name), | 2107 | snprintf(name, sizeof(name), |
| 2106 | "%s_ui%d", class_name(), dd->unit); | 2108 | "%s_ui%d", class_name(), dd->unit); |
| 2107 | ret = hfi1_cdev_init(dd->unit + UI_OFFSET, name, &ui_file_ops, | 2109 | ret = hfi1_cdev_init(dd->unit + UI_OFFSET, name, &ui_file_ops, |
| 2108 | &dd->ui_cdev, &dd->ui_device); | 2110 | &dd->ui_cdev, &dd->ui_device, |
| 2111 | false); | ||
| 2109 | if (ret) | 2112 | if (ret) |
| 2110 | goto done; | 2113 | goto done; |
| 2111 | } | 2114 | } |
