Skip to content

Commit dbd9f69

Browse files
committed
huion: Use allocated buffer for DMA
Allocate a buffer with kmalloc for receiving the parameters string descriptor with usb_control_msg, instead of using a buffer on the stack, as the latter is unsafe. Use an enum for indices into the buffer to ensure the buffer size if sufficient. This fixes the static checker error "doing dma on the stack (buf)". Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com>
1 parent bb3f47e commit dbd9f69

1 file changed

Lines changed: 38 additions & 12 deletions

File tree

hid-huion.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ static const __u8 huion_tablet_rdesc_template[] = {
8484
0xC0 /* End Collection */
8585
};
8686

87+
/* Parameter indices */
88+
enum huion_prm {
89+
HUION_PRM_X_LM = 1,
90+
HUION_PRM_Y_LM = 2,
91+
HUION_PRM_PRESSURE_LM = 4,
92+
HUION_PRM_RESOLUTION = 5,
93+
HUION_PRM_NUM
94+
};
95+
8796
/* Driver data */
8897
struct huion_drvdata {
8998
__u8 *rdesc;
@@ -115,7 +124,8 @@ static int huion_tablet_enable(struct hid_device *hdev)
115124
int rc;
116125
struct usb_device *usb_dev = hid_to_usb_dev(hdev);
117126
struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
118-
__le16 buf[6];
127+
__le16 *buf = NULL;
128+
size_t len;
119129
s32 params[HUION_PH_ID_NUM];
120130
s32 resolution;
121131
__u8 *p;
@@ -127,27 +137,38 @@ static int huion_tablet_enable(struct hid_device *hdev)
127137
* driver traffic.
128138
* NOTE: This enables fully-functional tablet mode.
129139
*/
140+
len = HUION_PRM_NUM * sizeof(*buf);
141+
buf = kmalloc(len, GFP_KERNEL);
142+
if (buf == NULL) {
143+
hid_err(hdev, "failed to allocate parameter buffer\n");
144+
rc = -ENOMEM;
145+
goto cleanup;
146+
}
130147
rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
131148
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
132149
(USB_DT_STRING << 8) + 0x64,
133-
0x0409, buf, sizeof(buf),
150+
0x0409, buf, len,
134151
USB_CTRL_GET_TIMEOUT);
135152
if (rc == -EPIPE) {
136153
hid_err(hdev, "device parameters not found\n");
137-
return -ENODEV;
154+
rc = -ENODEV;
155+
goto cleanup;
138156
} else if (rc < 0) {
139157
hid_err(hdev, "failed to get device parameters: %d\n", rc);
140-
return -ENODEV;
141-
} else if (rc != sizeof(buf)) {
158+
rc = -ENODEV;
159+
goto cleanup;
160+
} else if (rc != len) {
142161
hid_err(hdev, "invalid device parameters\n");
143-
return -ENODEV;
162+
rc = -ENODEV;
163+
goto cleanup;
144164
}
145165

146166
/* Extract device parameters */
147-
params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]);
148-
params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]);
149-
params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]);
150-
resolution = le16_to_cpu(buf[5]);
167+
params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[HUION_PRM_X_LM]);
168+
params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[HUION_PRM_Y_LM]);
169+
params[HUION_PH_ID_PRESSURE_LM] =
170+
le16_to_cpu(buf[HUION_PRM_PRESSURE_LM]);
171+
resolution = le16_to_cpu(buf[HUION_PRM_RESOLUTION]);
151172
if (resolution == 0) {
152173
params[HUION_PH_ID_X_PM] = 0;
153174
params[HUION_PH_ID_Y_PM] = 0;
@@ -164,7 +185,8 @@ static int huion_tablet_enable(struct hid_device *hdev)
164185
GFP_KERNEL);
165186
if (drvdata->rdesc == NULL) {
166187
hid_err(hdev, "failed to allocate fixed rdesc\n");
167-
return -ENOMEM;
188+
rc = -ENOMEM;
189+
goto cleanup;
168190
}
169191
drvdata->rsize = sizeof(huion_tablet_rdesc_template);
170192

@@ -183,7 +205,11 @@ static int huion_tablet_enable(struct hid_device *hdev)
183205
}
184206
}
185207

186-
return 0;
208+
rc = 0;
209+
210+
cleanup:
211+
kfree(buf);
212+
return rc;
187213
}
188214

189215
static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id)

0 commit comments

Comments
 (0)