diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-08-26 09:16:49 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-09-01 20:51:36 -0400 |
commit | 101b96f32956ee99bf1468afaf572b88cda9f88b (patch) | |
tree | 16e177755603dc88de93f71d285f0b1a3a1bd9c6 | |
parent | a3376e3ec81c5dd0622cbc187db76d2824d31c1c (diff) |
drm: fix DRM_IOCTL_MODE_GETFB handle-leak
DRM_IOCTL_MODE_GETFB is used to retrieve information about a given
framebuffer ID. It is a read-only helper and was thus declassified for
unprivileged access in:
commit a14b1b42477c5ef089fcda88cbaae50d979eb8f9
Author: Mandeep Singh Baines <mandeep.baines@gmail.com>
Date: Fri Jan 20 12:11:16 2012 -0800
drm: remove master fd restriction on mode setting getters
However, alongside width, height and stride information,
DRM_IOCTL_MODE_GETFB also passes back a handle to the underlying buffer of
the framebuffer. This handle allows users to mmap() it and read or write
into it. Obviously, this should be restricted to DRM-Master.
With the current setup, *any* process with access to /dev/dri/card0 (which
means any process with access to hardware-accelerated rendering) can
access the current screen framebuffer and modify it ad libitum.
For backwards-compatibility reasons we want to keep the
DRM_IOCTL_MODE_GETFB call unprivileged. Besides, it provides quite useful
information regarding screen setup. So we simply test whether the caller
is the current DRM-Master and if not, we return 0 as handle, which is
always invalid. A following DRM_IOCTL_GEM_CLOSE on this handle will fail
with EINVAL, but we accept this. Users shouldn't test for errors during
GEM_CLOSE, anyway. And it is still better as a failing MODE_GETFB call.
v2: add capable(CAP_SYS_ADMIN) check for compatibility with i-g-t
Cc: <stable@vger.kernel.org>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5ebc972c0b6d..bff2fa941f60 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -2641,10 +2641,22 @@ int drm_mode_getfb(struct drm_device *dev, | |||
2641 | r->depth = fb->depth; | 2641 | r->depth = fb->depth; |
2642 | r->bpp = fb->bits_per_pixel; | 2642 | r->bpp = fb->bits_per_pixel; |
2643 | r->pitch = fb->pitches[0]; | 2643 | r->pitch = fb->pitches[0]; |
2644 | if (fb->funcs->create_handle) | 2644 | if (fb->funcs->create_handle) { |
2645 | ret = fb->funcs->create_handle(fb, file_priv, &r->handle); | 2645 | if (file_priv->is_master || capable(CAP_SYS_ADMIN)) { |
2646 | else | 2646 | ret = fb->funcs->create_handle(fb, file_priv, |
2647 | &r->handle); | ||
2648 | } else { | ||
2649 | /* GET_FB() is an unprivileged ioctl so we must not | ||
2650 | * return a buffer-handle to non-master processes! For | ||
2651 | * backwards-compatibility reasons, we cannot make | ||
2652 | * GET_FB() privileged, so just return an invalid handle | ||
2653 | * for non-masters. */ | ||
2654 | r->handle = 0; | ||
2655 | ret = 0; | ||
2656 | } | ||
2657 | } else { | ||
2647 | ret = -ENODEV; | 2658 | ret = -ENODEV; |
2659 | } | ||
2648 | 2660 | ||
2649 | drm_framebuffer_unreference(fb); | 2661 | drm_framebuffer_unreference(fb); |
2650 | 2662 | ||