[Bug 188911] New: Function qxl_release_alloc() returns an improper value when the call to kmalloc() fails, resulting in bad memory access
bugzilla-daemon at bugzilla.kernel.org
bugzilla-daemon at bugzilla.kernel.org
Fri Nov 25 11:08:20 UTC 2016
https://bugzilla.kernel.org/show_bug.cgi?id=188911
Bug ID: 188911
Summary: Function qxl_release_alloc() returns an improper value
when the call to kmalloc() fails, resulting in bad
memory access
Product: Drivers
Version: 2.5
Kernel Version: linux-4.9-rc6
Hardware: All
OS: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: Video(DRI - non Intel)
Assignee: drivers_video-dri at kernel-bugs.osdl.org
Reporter: bianpan2010 at ruc.edu.cn
Regression: No
(1) Function kmalloc() return a NULL pointer if there is no enough memory. The
function qxl_release_alloc() defined in file drivers/gpu/drm/qxl/qxl_release.c
tries to allocate memory and stores in its third parameter @@ret. Parameter
@@ret keeps unmodified if the call to kmalloc() (at line 133) fails. In this
case, it returns 0.
(2) Function qxl_alloc_release_reserved() calls qxl_release_alloc() to allocate
memory for its parameter @@release. By reviewing the source code of the callers
of function qxl_alloc_release_reserved() (e.g. qxl_process_single_command()
defined in file drivers/gpu/drm/qxl/qxl_ioctl.c), we find that parameter
@@release is uninitialized. The return value of qxl_release_alloc() is checked,
if the return value is 0, the execution flow will continue, and the memory
pointed by @@release will be accessed (at line 368). Recall that function
qxl_release_alloc() returns 0 when kmalloc() fails. In this case, the
uninitialized memory will be accessed, causing bad memory access.
(3) To avoid bad memory access, it's better to return "-ENOMEM" when the call
to kmalloc() fails in function qxl_release_alloc().
Codes related to this bug are summarised as follows.
(1) qxl_release_alloc @@ drivers/gpu/drm/qxl/qxl_release.c
125 static int
126 qxl_release_alloc(struct qxl_device *qdev, int type,
127 struct qxl_release **ret)
128 {
129 struct qxl_release *release;
130 int handle;
131 size_t size = sizeof(*release);
132
133 release = kmalloc(size, GFP_KERNEL);
134 if (!release) {
135 DRM_ERROR("Out of memory\n");
136 return 0; // "return -ENOMEM;"?
137 }
...
155 *ret = release;
156 QXL_INFO(qdev, "allocated release %d\n", handle);
157 release->id = handle;
158 return handle;
159 }
(2) qxl_alloc_release_reserved @@ drivers/gpu/drm/qxl/qxl_release.c
323 int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
324 int type, struct qxl_release **release,
325 struct qxl_bo **rbo)
326 {
327 struct qxl_bo *bo;
328 int idr_ret;
...
344 idr_ret = qxl_release_alloc(qdev, type, release);
345 if (idr_ret < 0) {
346 if (rbo)
347 *rbo = NULL;
348 return idr_ret;
349 }
...
366 bo = qxl_bo_ref(qdev->current_release_bo[cur_idx]);
367
// bad memory access when kmalloc() fails?
368 (*release)->release_offset = qdev->current_release_bo_offset[cur_idx] *
release_size_per_bo[cur_idx];
369 qdev->current_release_bo_offset[cur_idx]++;
...
388 }
(3) qxl_process_single_command @@ drivers/gpu/drm/qxl/qxl_ioctl.c
138 static int qxl_process_single_command(struct qxl_device *qdev,
139 struct drm_qxl_command *cmd,
140 struct drm_file *file_priv)
141 {
142 struct qxl_reloc_info *reloc_info;
143 int release_type;
144 struct qxl_release *release; // release is not initialized
...
175 ret = qxl_alloc_release_reserved(qdev,
176 sizeof(union qxl_release_info) +
177 cmd->command_size,
178 release_type,
179 &release,
180 &cmd_bo);
181 if (ret)
182 goto out_free_reloc;
...
269 out_free_reloc:
270 kfree(reloc_info);
271 return ret;
272 }
Thanks very much!
--
You are receiving this mail because:
You are watching the assignee of the bug.
More information about the dri-devel
mailing list