Commit 148a8653 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau: block a bunch of classes from userspace

Long ago, there had been plans for making use of a bunch of these APIs
from userspace and there's various checks in place to stop misbehaving.

Countless other projects have occurred in the meantime, and the pieces
didn't finish falling into place for that to happen.

They will (hopefully) in the not-too-distant future, but it won't look
quite as insane.  The super checks are causing problems right now, and
are going to be removed.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 50c4a644
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
struct nv_device_v0 { struct nv_device_v0 {
__u8 version; __u8 version;
__u8 pad01[7]; __u8 priv;
__u8 pad02[6];
__u64 device; /* device identifier, ~0 for client default */ __u64 device; /* device identifier, ~0 for client default */
}; };
......
...@@ -244,6 +244,7 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname, ...@@ -244,6 +244,7 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
ret = nvif_device_ctor(&cli->base.object, "drmDevice", 0, NV_DEVICE, ret = nvif_device_ctor(&cli->base.object, "drmDevice", 0, NV_DEVICE,
&(struct nv_device_v0) { &(struct nv_device_v0) {
.device = ~0, .device = ~0,
.priv = true,
}, sizeof(struct nv_device_v0), }, sizeof(struct nv_device_v0),
&cli->device); &cli->device);
if (ret) { if (ret) {
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
#include <nvif/event.h> #include <nvif/event.h>
#include <nvif/ioctl.h> #include <nvif/ioctl.h>
#include <nvif/class.h>
#include <nvif/cl0080.h>
struct usif_notify_p { struct usif_notify_p {
struct drm_pending_event base; struct drm_pending_event base;
struct { struct {
...@@ -261,7 +264,7 @@ usif_object_dtor(struct usif_object *object) ...@@ -261,7 +264,7 @@ usif_object_dtor(struct usif_object *object)
} }
static int static int
usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc) usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc, bool parent_abi16)
{ {
struct nouveau_cli *cli = nouveau_cli(f); struct nouveau_cli *cli = nouveau_cli(f);
struct nvif_client *client = &cli->base; struct nvif_client *client = &cli->base;
...@@ -271,23 +274,48 @@ usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc) ...@@ -271,23 +274,48 @@ usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
struct usif_object *object; struct usif_object *object;
int ret = -ENOSYS; int ret = -ENOSYS;
if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true)))
return ret;
switch (args->v0.oclass) {
case NV_DMA_FROM_MEMORY:
case NV_DMA_TO_MEMORY:
case NV_DMA_IN_MEMORY:
return -EINVAL;
case NV_DEVICE: {
union {
struct nv_device_v0 v0;
} *args = data;
if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false)))
return ret;
args->v0.priv = false;
break;
}
default:
if (!parent_abi16)
return -EINVAL;
break;
}
if (!(object = kmalloc(sizeof(*object), GFP_KERNEL))) if (!(object = kmalloc(sizeof(*object), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
list_add(&object->head, &cli->objects); list_add(&object->head, &cli->objects);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { object->route = args->v0.route;
object->route = args->v0.route; object->token = args->v0.token;
object->token = args->v0.token; args->v0.route = NVDRM_OBJECT_USIF;
args->v0.route = NVDRM_OBJECT_USIF; args->v0.token = (unsigned long)(void *)object;
args->v0.token = (unsigned long)(void *)object; ret = nvif_client_ioctl(client, argv, argc);
ret = nvif_client_ioctl(client, argv, argc); if (ret) {
args->v0.token = object->token; usif_object_dtor(object);
args->v0.route = object->route; return ret;
} }
if (ret) args->v0.token = object->token;
usif_object_dtor(object); args->v0.route = object->route;
return ret; return 0;
} }
int int
...@@ -301,6 +329,7 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc) ...@@ -301,6 +329,7 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
struct nvif_ioctl_v0 v0; struct nvif_ioctl_v0 v0;
} *argv = data; } *argv = data;
struct usif_object *object; struct usif_object *object;
bool abi16 = false;
u8 owner; u8 owner;
int ret; int ret;
...@@ -331,11 +360,13 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc) ...@@ -331,11 +360,13 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
mutex_unlock(&cli->mutex); mutex_unlock(&cli->mutex);
goto done; goto done;
} }
abi16 = true;
} }
switch (argv->v0.type) { switch (argv->v0.type) {
case NVIF_IOCTL_V0_NEW: case NVIF_IOCTL_V0_NEW:
ret = usif_object_new(filp, data, size, argv, argc); ret = usif_object_new(filp, data, size, argv, argc, abi16);
break; break;
case NVIF_IOCTL_V0_NTFY_NEW: case NVIF_IOCTL_V0_NTFY_NEW:
ret = usif_notify_new(filp, data, size, argv, argc); ret = usif_notify_new(filp, data, size, argv, argc);
......
...@@ -397,7 +397,7 @@ nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size, ...@@ -397,7 +397,7 @@ nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size,
return ret; return ret;
/* give priviledged clients register access */ /* give priviledged clients register access */
if (client->super) if (args->v0.priv)
func = &nvkm_udevice_super; func = &nvkm_udevice_super;
else else
func = &nvkm_udevice; func = &nvkm_udevice;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment