Thread (97 messages) 97 messages, 14 authors, 2022-11-03

Re: [PATCH v8 1/8] mm/memfd: Introduce userspace inaccessible memfd

From: Fuad Tabba <hidden>
Date: 2022-09-30 16:15:11
Also in: kvm, linux-doc, linux-fsdevel, linux-mm, lkml, qemu-devel

Hi,

<...>
quoted hunk ↗ jump to hunk
diff --git a/mm/memfd_inaccessible.c b/mm/memfd_inaccessible.c
new file mode 100644
index 000000000000..2d33cbdd9282
--- /dev/null
+++ b/mm/memfd_inaccessible.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "linux/sbitmap.h"
+#include <linux/memfd.h>
+#include <linux/pagemap.h>
+#include <linux/pseudo_fs.h>
+#include <linux/shmem_fs.h>
+#include <uapi/linux/falloc.h>
+#include <uapi/linux/magic.h>
+
+struct inaccessible_data {
+       struct mutex lock;
+       struct file *memfd;
+       struct list_head notifiers;
+};
+
+static void inaccessible_notifier_invalidate(struct inaccessible_data *data,
+                                pgoff_t start, pgoff_t end)
+{
+       struct inaccessible_notifier *notifier;
+
+       mutex_lock(&data->lock);
+       list_for_each_entry(notifier, &data->notifiers, list) {
+               notifier->ops->invalidate(notifier, start, end);
+       }
+       mutex_unlock(&data->lock);
+}
+
+static int inaccessible_release(struct inode *inode, struct file *file)
+{
+       struct inaccessible_data *data = inode->i_mapping->private_data;
+
+       fput(data->memfd);
+       kfree(data);
+       return 0;
+}
+
+static long inaccessible_fallocate(struct file *file, int mode,
+                                  loff_t offset, loff_t len)
+{
+       struct inaccessible_data *data = file->f_mapping->private_data;
+       struct file *memfd = data->memfd;
+       int ret;
+
+       if (mode & FALLOC_FL_PUNCH_HOLE) {
+               if (!PAGE_ALIGNED(offset) || !PAGE_ALIGNED(len))
+                       return -EINVAL;
+       }
+
+       ret = memfd->f_op->fallocate(memfd, mode, offset, len);
I think that shmem_file_operations.fallocate is only set if
CONFIG_TMPFS is enabled (shmem.c). Should there be a check at
initialization that fallocate is set, or maybe a config dependency, or
can we count on it always being enabled?
+       inaccessible_notifier_invalidate(data, offset, offset + len);
+       return ret;
+}
+
<...>
+void inaccessible_register_notifier(struct file *file,
+                                   struct inaccessible_notifier *notifier)
+{
+       struct inaccessible_data *data = file->f_mapping->private_data;
+
+       mutex_lock(&data->lock);
+       list_add(&notifier->list, &data->notifiers);
+       mutex_unlock(&data->lock);
+}
+EXPORT_SYMBOL_GPL(inaccessible_register_notifier);
If the memfd wasn't marked as inaccessible, or more generally
speaking, if the file isn't a memfd_inaccessible file, this ends up
accessing an uninitialized pointer for the notifier list. Should there
be a check for that here, and have this function return an error if
that's not the case?

Thanks,
/fuad


+
+void inaccessible_unregister_notifier(struct file *file,
+                                     struct inaccessible_notifier *notifier)
+{
+       struct inaccessible_data *data = file->f_mapping->private_data;
+
+       mutex_lock(&data->lock);
+       list_del(&notifier->list);
+       mutex_unlock(&data->lock);
+}
+EXPORT_SYMBOL_GPL(inaccessible_unregister_notifier);
+
+int inaccessible_get_pfn(struct file *file, pgoff_t offset, pfn_t *pfn,
+                        int *order)
+{
+       struct inaccessible_data *data = file->f_mapping->private_data;
+       struct file *memfd = data->memfd;
+       struct page *page;
+       int ret;
+
+       ret = shmem_getpage(file_inode(memfd), offset, &page, SGP_WRITE);
+       if (ret)
+               return ret;
+
+       *pfn = page_to_pfn_t(page);
+       *order = thp_order(compound_head(page));
+       SetPageUptodate(page);
+       unlock_page(page);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(inaccessible_get_pfn);
+
+void inaccessible_put_pfn(struct file *file, pfn_t pfn)
+{
+       struct page *page = pfn_t_to_page(pfn);
+
+       if (WARN_ON_ONCE(!page))
+               return;
+
+       put_page(page);
+}
+EXPORT_SYMBOL_GPL(inaccessible_put_pfn);
--
2.25.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help