[Mesa-dev] [PATCH v3 3/3] egl/android: Add DRM node probing and filtering
Amit Pundir
amit.pundir at linaro.org
Wed Jun 13 18:19:46 UTC 2018
On 13 June 2018 at 20:45, Rob Herring <robh at kernel.org> wrote:
>
> +Amit and John
>
> On Sat, Jun 9, 2018 at 11:27 AM, Robert Foss <robert.foss at collabora.com> wrote:
> > This patch both adds support for probing & filtering DRM nodes
> > and switches away from using the GRALLOC_MODULE_PERFORM_GET_DRM_FD
> > gralloc call.
> >
> > Currently the filtering is based just on the driver name,
> > and the desired name is supplied using the "drm.gpu.vendor_name"
> > Android property.
>
> There's a potential issue with this whole approach and that is
> SELinux. With the way SELinux locks down accesses, getting probing
> thru device files to work can be a pain. It may be better now than the
> prior version because sysfs is not probed. I'll leave it to Amit or
> John to comment.
Right.. so ICYMI, this patch is already pulled into external/mesa3d
project of AOSP and I stumbled upon one such /dev/dri/ access denial
on db820c recently.
In AOSP, zygote spawned apps already have access to GPU device nodes
in the form of /dev/gpu_device file, but the missing part is the
open-read access to "/dev/dri/" which need to be allowed explicitly.
Rest of the denials related to sysfs access can be easily resolved
using audit2allow tool.
Regards,
Amit Pundir
>
> Rob
>
> >
> > Signed-off-by: Robert Foss <robert.foss at collabora.com>
> > ---
> >
> > Changes since v2:
> > - Switch from drmGetDevices2 to manual renderD node iteration
> > - Add probe_res enum to communicate probing results better
> > - Avoid using _eglError() in internal static functions
> > - Avoid actually loading the driver while probing, just verify
> > that it exists.
> > - Replace strlen call with the assumed length PROPERTY_VALUE_MAX
> >
> > Changes since v1:
> > - Do not rely on libdrm for probing
> > - Distinguish between errors and when no drm devices are found
> >
> > Changes since RFC:
> > - Rebased on newer libdrm drmHandleMatch patch
> > - Added support for driver probing
> >
> >
> > src/egl/drivers/dri2/platform_android.c | 222 ++++++++++++++++++------
> > 1 file changed, 169 insertions(+), 53 deletions(-)
> >
> > diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
> > index 4ba96aad90..a2cbe92d93 100644
> > --- a/src/egl/drivers/dri2/platform_android.c
> > +++ b/src/egl/drivers/dri2/platform_android.c
> > @@ -27,12 +27,16 @@
> > * DEALINGS IN THE SOFTWARE.
> > */
> >
> > +#include <cutils/properties.h>
> > #include <errno.h>
> > +#include <dirent.h>
> > #include <dlfcn.h>
> > #include <fcntl.h>
> > #include <xf86drm.h>
> > #include <stdbool.h>
> > +#include <stdio.h>
> > #include <sync/sync.h>
> > +#include <sys/types.h>
> >
> > #include "loader.h"
> > #include "egl_dri2.h"
> > @@ -1130,31 +1134,6 @@ droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
> > return (config_count != 0);
> > }
> >
> > -enum {
> > - /* perform(const struct gralloc_module_t *mod,
> > - * int op,
> > - * int *fd);
> > - */
> > - GRALLOC_MODULE_PERFORM_GET_DRM_FD = 0x40000002,
> > -};
> > -
> > -static int
> > -droid_open_device(struct dri2_egl_display *dri2_dpy)
> > -{
> > - int fd = -1, err = -EINVAL;
> > -
> > - if (dri2_dpy->gralloc->perform)
> > - err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc,
> > - GRALLOC_MODULE_PERFORM_GET_DRM_FD,
> > - &fd);
> > - if (err || fd < 0) {
> > - _eglLog(_EGL_WARNING, "fail to get drm fd");
> > - fd = -1;
> > - }
> > -
> > - return (fd >= 0) ? fcntl(fd, F_DUPFD_CLOEXEC, 3) : -1;
> > -}
> > -
> > static const struct dri2_egl_display_vtbl droid_display_vtbl = {
> > .authenticate = NULL,
> > .create_window_surface = droid_create_window_surface,
> > @@ -1215,6 +1194,168 @@ static const __DRIextension *droid_image_loader_extensions[] = {
> > NULL,
> > };
> >
> > +EGLBoolean
> > +droid_load_driver(_EGLDisplay *disp)
> > +{
> > + struct dri2_egl_display *dri2_dpy = disp->DriverData;
> > + const char *err;
> > +
> > + dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
> > + if (dri2_dpy->driver_name == NULL)
> > + return false;
> > +
> > + dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
> > +
> > + if (!dri2_dpy->is_render_node) {
> > + #ifdef HAVE_DRM_GRALLOC
> > + /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names
> > + * for backwards compatibility with drm_gralloc. (Do not use on new
> > + * systems.) */
> > + dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
> > + if (!dri2_load_driver(disp)) {
> > + err = "DRI2: failed to load driver";
> > + goto error;
> > + }
> > + #else
> > + err = "DRI2: handle is not for a render node";
> > + goto error;
> > + #endif
> > + } else {
> > + dri2_dpy->loader_extensions = droid_image_loader_extensions;
> > + if (!dri2_load_driver_dri3(disp)) {
> > + err = "DRI3: failed to load driver";
> > + goto error;
> > + }
> > + }
> > +
> > + return true;
> > +
> > +error:
> > + free(dri2_dpy->driver_name);
> > + dri2_dpy->driver_name = NULL;
> > + return false;
> > +}
> > +
> > +static bool
> > +droid_probe_driver(int fd)
> > +{
> > + char *driver_name;
> > +
> > + driver_name = loader_get_driver_for_fd(fd);
> > + if (driver_name == NULL)
> > + return false;
> > +
> > + free(driver_name);
> > + return true;
> > +}
> > +
> > +typedef enum {
> > + probe_error = -1,
> > + probe_success = 0,
> > + probe_filtered_out = 1,
> > + probe_no_driver = 2
> > +} probe_ret_t;
> > +
> > +static probe_ret_t
> > +droid_probe_device(_EGLDisplay *disp, int fd, char *vendor)
> > +{
> > + int ret;
> > +
> > + drmVersionPtr ver = drmGetVersion(fd);
> > + if (!ver)
> > + return probe_error;
> > +
> > + if (vendor != NULL && ver->name != NULL &&
> > + strncmp(vendor, ver->name, PROPERTY_VALUE_MAX) != 0) {
> > + ret = probe_filtered_out;
> > + goto cleanup;
> > + }
> > +
> > +
> > + if (!droid_probe_driver(fd)) {
> > + ret = probe_no_driver;
> > + goto cleanup;
> > + }
> > +
> > + ret = probe_success;
> > +
> > +cleanup:
> > + drmFreeVersion(ver);
> > + return ret;
> > +}
> > +
> > +static int
> > +droid_open_device(_EGLDisplay *disp)
> > +{
> > + const int MAX_DRM_DEVICES = 32;
> > + int prop_set, num_devices;
> > + int fd = -1, fallback_fd = -1;
> > +
> > + char *vendor_name = NULL;
> > + char vendor_buf[PROPERTY_VALUE_MAX];
> > + if (property_get("drm.gpu.vendor_name", vendor_buf, NULL) > 0);
> > + vendor_name = vendor_buf;
> > +
> > + const char *drm_dir_name = "/dev/dri";
> > + DIR *sysdir = opendir(drm_dir_name);
> > + if (!sysdir)
> > + return -errno;
> > +
> > + struct dirent *dent;
> > + while ((dent = readdir(sysdir))) {
> > + char dev_path[128];
> > + char *render_dev_prefix = "renderD";
> > + size_t prefix_len = strlen(render_dev_prefix);
> > +
> > + if (strncmp(render_dev_prefix, dent->d_name, prefix_len) != 0)
> > + continue;
> > +
> > + sprintf(dev_path, "%s/%s", drm_dir_name, dent->d_name);
> > + fd = loader_open_device(dev_path);
> > + if (fd == -1) {
> > + _eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s",
> > + __func__, dev_path);
> > + continue;
> > + }
> > +
> > + int ret = droid_probe_device(disp, fd, vendor_name);
> > + switch (ret) {
> > + case probe_success:
> > + goto success;
> > + case probe_filtered_out:
> > + goto allow_fallback;
> > + case probe_error:
> > + case probe_no_driver:
> > + goto next;
> > + }
> > +
> > +allow_fallback:
> > + if (fallback_fd == -1)
> > + fallback_fd = fd;
> > +next:
> > + if (fallback_fd != fd)
> > + close(fd);
> > + fd = -1;
> > + continue;
> > + }
> > +
> > +success:
> > + closedir(sysdir);
> > +
> > + if (fallback_fd < 0 && fd < 0) {
> > + _eglLog(_EGL_WARNING, "Failed to open any DRM device");
> > + return -1;
> > + }
> > +
> > + if (fd < 0) {
> > + _eglLog(_EGL_WARNING, "Failed to open desired DRM device, using fallback");
> > + return fallback_fd;
> > + }
> > +
> > + close(fallback_fd);
> > + return fd;
> > +}
> > +
> > EGLBoolean
> > dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
> > {
> > @@ -1242,42 +1383,17 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
> >
> > disp->DriverData = (void *) dri2_dpy;
> >
> > - dri2_dpy->fd = droid_open_device(dri2_dpy);
> > + dri2_dpy->fd = droid_open_device(disp);
> > if (dri2_dpy->fd < 0) {
> > err = "DRI2: failed to open device";
> > goto cleanup;
> > }
> >
> > - dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
> > - if (dri2_dpy->driver_name == NULL) {
> > - err = "DRI2: failed to get driver name";
> > + if (!droid_load_driver(disp)) {
> > + err = "DRI2: failed to load driver";
> > goto cleanup;
> > }
> >
> > - dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
> > -
> > - if (!dri2_dpy->is_render_node) {
> > - #ifdef HAVE_DRM_GRALLOC
> > - /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names
> > - * for backwards compatibility with drm_gralloc. (Do not use on new
> > - * systems.) */
> > - dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
> > - if (!dri2_load_driver(disp)) {
> > - err = "DRI2: failed to load driver";
> > - goto cleanup;
> > - }
> > - #else
> > - err = "DRI2: handle is not for a render node";
> > - goto cleanup;
> > - #endif
> > - } else {
> > - dri2_dpy->loader_extensions = droid_image_loader_extensions;
> > - if (!dri2_load_driver_dri3(disp)) {
> > - err = "DRI3: failed to load driver";
> > - goto cleanup;
> > - }
> > - }
> > -
> > if (!dri2_create_screen(disp)) {
> > err = "DRI2: failed to create screen";
> > goto cleanup;
> > --
> > 2.17.1
> >
More information about the mesa-dev
mailing list