mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 02:19:51 +00:00
drm: Round size of SHM maps to PAGE_SIZE
Currently, userspace can fail to obtain the SAREA mapping (among other reasons) if it passes SAREA_MAX to drmAddMap without aligning it to the page size. This breaks for example on PowerPC with 64K pages and radeon despite the kernel radeon actually doing the right rouding in the first place. The way SAREA_MAX is defined with a bunch of ifdef's and duplicated between libdrm and the X server is gross, ultimately it should be retrieved by userspace from the kernel, but in the meantime, we have plenty of existing userspace built with bad values that need to work. This patch works around broken userspace by rounding the requested size in drm_addmap_core() of any SHM map to the page size. Since the backing memory for SHM maps is also allocated within addmap_core, there is no danger of adjacent memory being exposed due to the increased map size. The only side effect is that drivers that previously tried to create or access SHM maps using a size < PAGE_SIZE and failed (getting -EINVAL), will now succeed at the cost of a little bit more memory used if that happens to be when the map is created. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
279e677faa
commit
b674137755
1 changed files with 8 additions and 0 deletions
|
@ -170,6 +170,14 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
|
||||||
}
|
}
|
||||||
DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
|
DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
|
||||||
(unsigned long long)map->offset, map->size, map->type);
|
(unsigned long long)map->offset, map->size, map->type);
|
||||||
|
|
||||||
|
/* page-align _DRM_SHM maps. They are allocated here so there is no security
|
||||||
|
* hole created by that and it works around various broken drivers that use
|
||||||
|
* a non-aligned quantity to map the SAREA. --BenH
|
||||||
|
*/
|
||||||
|
if (map->type == _DRM_SHM)
|
||||||
|
map->size = PAGE_ALIGN(map->size);
|
||||||
|
|
||||||
if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
|
if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
|
||||||
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
Loading…
Reference in a new issue