Add a new dma-buf ioctl() op, DMA_BUF_IOCTL_REVOKE, connected to a new
(optional) dma_buf_ops callback, revoke().  An exporter receiving this
will _permanently_ revoke the DMABUF, meaning it can no longer be
mapped/attached/mmap()ed.  It also guarantees that existing
importers have been detached (e.g. via move_notify) and all mappings
made inaccessible.

This is useful for lifecycle management in scenarios where a process
has created a DMABUF representing a resource, then delegated it to
a client process; access to the resource is revoked when the client is
deemed "done", and the resource can be safely re-used elsewhere.

Signed-off-by: Matt Evans <[email protected]>
---
 drivers/dma-buf/dma-buf.c    |  5 +++++
 include/linux/dma-buf.h      | 22 ++++++++++++++++++++++
 include/uapi/linux/dma-buf.h |  1 +
 3 files changed, 28 insertions(+)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index edaa9e4ee4ae..b9b315317f2d 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -561,6 +561,11 @@ static long dma_buf_ioctl(struct file *file,
        case DMA_BUF_IOCTL_IMPORT_SYNC_FILE:
                return dma_buf_import_sync_file(dmabuf, (const void __user 
*)arg);
 #endif
+       case DMA_BUF_IOCTL_REVOKE:
+               if (dmabuf->ops->revoke)
+                       return dmabuf->ops->revoke(dmabuf);
+               else
+                       return -EINVAL;
 
        default:
                return -ENOTTY;
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 0bc492090237..a68c9ad7aebd 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -277,6 +277,28 @@ struct dma_buf_ops {
 
        int (*vmap)(struct dma_buf *dmabuf, struct iosys_map *map);
        void (*vunmap)(struct dma_buf *dmabuf, struct iosys_map *map);
+
+       /**
+        * @revoke:
+        *
+        * This callback is invoked from a userspace
+        * DMA_BUF_IOCTL_REVOKE operation, and requests that access to
+        * the buffer is immediately and permanently revoked.  On
+        * successful return, the buffer is not accessible through any
+        * mmap() or dma-buf import.  The request fails if the buffer
+        * is pinned; otherwise, the exporter marks the buffer as
+        * inaccessible and uses the move_notify callback to inform
+        * importers of the change.  The buffer is permanently
+        * disabled, and the exporter must refuse all map, mmap,
+        * attach, etc. requests.
+        *
+        * Returns:
+        *
+        * 0 on success, or a negative error code on failure:
+        * -ENODEV if the associated device no longer exists/is closed.
+        * -EBADFD if the buffer has already been revoked.
+        */
+       int (*revoke)(struct dma_buf *dmabuf);
 };
 
 /**
diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h
index 5a6fda66d9ad..84bf2dd2d0f3 100644
--- a/include/uapi/linux/dma-buf.h
+++ b/include/uapi/linux/dma-buf.h
@@ -178,5 +178,6 @@ struct dma_buf_import_sync_file {
 #define DMA_BUF_SET_NAME_B     _IOW(DMA_BUF_BASE, 1, __u64)
 #define DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct 
dma_buf_export_sync_file)
 #define DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW(DMA_BUF_BASE, 3, struct 
dma_buf_import_sync_file)
+#define DMA_BUF_IOCTL_REVOKE   _IO(DMA_BUF_BASE, 4)
 
 #endif
-- 
2.47.3

Reply via email to