diff options
author | Emil Velikov <emil.velikov@collabora.com> | 2019-02-08 17:49:37 +0000 |
---|---|---|
committer | Emil Velikov <emil.l.velikov@gmail.com> | 2019-02-13 13:12:23 +0000 |
commit | 90f78ac704718a4dc089ca99041f032191c6f8b1 (patch) | |
tree | d7c06677e05b41e485b4321c7bc791a72514b9c5 /tests/core_auth.c | |
parent | 3e65dd7a48f466187afd0c27ff2b07c20e6b3938 (diff) |
tests/core_unauth_vs_render: new test for the relaxed DRM_AUTH handling
As the inline comment says, this test checks that the kernel allows
unauthenticated master with render capable, RENDER_ALLOW ioctls.
The kernel commit has extra details why.
v2:
- drop RUN_AS_ROOT guard
- call check_auth() on the {,un}authenticated device
- check the device is PRIME (import) capable
- check the device has render node
- tweak expectations based on above three
- elaborate why we care only about -EACCES
v3:
- fold into existing core_auth.c
- move igt_assert within the subtest
- make has_prime_import() an igt_require()
- check for BADF before and after, as requested. Not strictly needed.
- swap igt_info+drm_open_driver with comment + __drm_open_driver
Former calls igt_skip() which is problematic with igt_fork().
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> (irc)
Diffstat (limited to 'tests/core_auth.c')
-rw-r--r-- | tests/core_auth.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/tests/core_auth.c b/tests/core_auth.c index 0c016a37..0b9073cb 100644 --- a/tests/core_auth.c +++ b/tests/core_auth.c @@ -1,5 +1,6 @@ /* * Copyright 2015 David Herrmann <dh.herrmann@gmail.com> + * Copyright 2018 Collabora, Ltd * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -40,6 +41,7 @@ #include <sys/time.h> #include <sys/poll.h> #include <sys/resource.h> +#include <sys/sysmacros.h> #include "drm.h" #ifdef __linux__ @@ -190,6 +192,98 @@ static void test_basic_auth(int master) close(slave); } +static bool has_prime_import(int fd) +{ + uint64_t value; + + if (drmGetCap(fd, DRM_CAP_PRIME, &value)) + return false; + + return value & DRM_PRIME_CAP_IMPORT; +} + +static void check_auth_sanity(int master) +{ + uint32_t handle; + + igt_assert(check_auth(master) == true); + igt_require(has_prime_import(master)); + + igt_assert(drmPrimeFDToHandle(master, -1, &handle) < 0); + + /* IOCTL requires authenticated master as done in drm_permit. + * As we get past that, we'll fail due to the invalid FD. + * + * Note: strictly speaking this is unrelated to the goal of + * the test, although danvet requested it. + */ + igt_assert(errno == EBADF); +} + +static bool has_render_node(int fd) +{ + char node_name[80]; + struct stat sbuf; + + if (fstat(fd, &sbuf)) + return false; + + sprintf(node_name, "/dev/dri/renderD%d", minor(sbuf.st_rdev) | 0x80); + if (stat(node_name, &sbuf)) + return false; + + return true; +} + +/* + * Testcase: Render capable, unauthenticated master doesn't throw -EACCES for + * DRM_RENDER_ALLOW ioctls. + */ +static void test_unauth_vs_render(int master) +{ + int slave; + uint32_t handle; + + /* + * FIXME: when drm_open_driver() fails to open() a node (insufficient + * permissions or otherwise, it will igt_skip. + * As of today, igt_skip and igt_fork do not work together. + */ + slave = __drm_open_driver(DRIVER_ANY); + /* + * FIXME: relate to the master fd passed with the above open and fix + * all of IGT. + */ + + igt_assert(slave >= 0); + + /* + * The second open() happens without CAP_SYS_ADMIN, thus it will NOT + * be authenticated. + */ + igt_assert(check_auth(slave) == false); + + /* Issuing the following ioctl will fail, no doubt about it. */ + igt_assert(drmPrimeFDToHandle(slave, -1, &handle) < 0); + + /* + * Updated kernels allow render capable, unauthenticated master to + * issue DRM_AUTH ioctls (like FD2HANDLE above), as long as they are + * annotated as DRM_RENDER_ALLOW. + * + * Otherwise, errno is set to -EACCES + * + * Note: We are _not_ interested in the FD2HANDLE specific errno, + * yet the EBADF check is added on the explicit request by danvet. + */ + if (has_render_node(slave)) + igt_assert(errno == EBADF); + else + igt_assert(errno == EACCES); + + close(slave); +} + igt_main { int master; @@ -228,4 +322,19 @@ igt_main igt_subtest("many-magics") test_many_magics(master); } + + igt_subtest_group { + igt_fixture + master = drm_open_driver(DRIVER_ANY); + + igt_subtest("unauth-vs-render") { + check_auth_sanity(master); + + igt_fork(child, 1) { + igt_drop_root(); + test_unauth_vs_render(master); + } + igt_waitchildren(); + } + } } |