diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index dc70ba90247e..c94e9ce46cc3 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -456,3 +456,4 @@
 449	i386	futex_waitv		sys_futex_waitv
 450	i386	set_mempolicy_home_node		sys_set_mempolicy_home_node
 451	i386	memfd_restricted	sys_memfd_restricted
+452	i386	memfd_restricted_bind	sys_memfd_restricted_bind
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index 06516abc8318..6bd86b45d63a 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -373,6 +373,7 @@
 449	common	futex_waitv		sys_futex_waitv
 450	common	set_mempolicy_home_node	sys_set_mempolicy_home_node
 451	common	memfd_restricted	sys_memfd_restricted
+452	common	memfd_restricted_bind	sys_memfd_restricted_bind
 
 #
 # Due to a historical design error, certain syscalls are numbered differently
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 15facd9de087..af62233df0c0 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -126,7 +126,7 @@ struct shared_policy {
 
 int vma_dup_policy(struct vm_area_struct *src, struct vm_area_struct *dst);
 struct mempolicy *mpol_create(
-	unsigned long mode, const unsigned long __user *nmask, unsigned long maxnode)
+	unsigned long mode, const unsigned long __user *nmask, unsigned long maxnode);
 void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol);
 int __mpol_set_shared_policy(struct shared_policy *info, struct mempolicy *mpol,
 			     unsigned long pgoff_start, unsigned long npages);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 660be0bf89d5..852b202d3837 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1059,6 +1059,11 @@ asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long l
 					    unsigned long home_node,
 					    unsigned long flags);
 asmlinkage long sys_memfd_restricted(unsigned int flags);
+asmlinkage long sys_memfd_restricted_bind(int fd, struct file_range __user *range,
+					  unsigned long mode,
+					  const unsigned long __user *nmask,
+					  unsigned long maxnode,
+					  unsigned int flags);
 
 /*
  * Architecture-specific system calls
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index e2ea7cd964f8..b5a1385bb4a7 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -889,10 +889,13 @@ __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
 #ifdef __ARCH_WANT_MEMFD_RESTRICTED
 #define __NR_memfd_restricted 451
 __SYSCALL(__NR_memfd_restricted, sys_memfd_restricted)
+
+#define __NR_memfd_restricted_bind 452
+__SYSCALL(__NR_memfd_restricted_bind, sys_memfd_restricted_bind)
 #endif
 
 #undef __NR_syscalls
-#define __NR_syscalls 452
+#define __NR_syscalls 453
 
 /*
  * 32 bit systems traditionally used different
diff --git a/include/uapi/linux/mempolicy.h b/include/uapi/linux/mempolicy.h
index 046d0ccba4cd..979499abd253 100644
--- a/include/uapi/linux/mempolicy.h
+++ b/include/uapi/linux/mempolicy.h
@@ -6,9 +6,9 @@
 #ifndef _UAPI_LINUX_MEMPOLICY_H
 #define _UAPI_LINUX_MEMPOLICY_H
 
+#include <asm-generic/posix_types.h>
 #include <linux/errno.h>
 
-
 /*
  * Both the MPOL_* mempolicy mode and the MPOL_F_* optional mode flags are
  * passed by the user to either set_mempolicy() or mbind() in an 'int' actual.
@@ -72,4 +72,9 @@ enum {
 #define RECLAIM_WRITE	(1<<1)	/* Writeout pages during reclaim */
 #define RECLAIM_UNMAP	(1<<2)	/* Unmap pages during reclaim */
 
+struct file_range {
+	__kernel_loff_t offset;
+	__kernel_size_t len;
+};
+
 #endif /* _UAPI_LINUX_MEMPOLICY_H */
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 7c4a32cbd2e7..db24d3fe6dc5 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -362,6 +362,7 @@ COND_SYSCALL(memfd_secret);
 
 /* memfd_restricted */
 COND_SYSCALL(memfd_restricted);
+COND_SYSCALL(memfd_restricted_bind);
 
 /*
  * Architecture specific weak syscall entries.
diff --git a/mm/restrictedmem.c b/mm/restrictedmem.c
index 55e99e6c09a1..9c249722c61b 100644
--- a/mm/restrictedmem.c
+++ b/mm/restrictedmem.c
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/mempolicy.h>
 #include "linux/sbitmap.h"
 #include <linux/pagemap.h>
 #include <linux/pseudo_fs.h>
@@ -359,3 +360,77 @@ int restrictedmem_get_page(struct file *file, pgoff_t offset,
 	return 0;
 }
 EXPORT_SYMBOL_GPL(restrictedmem_get_page);
+
+static int restrictedmem_set_shared_policy(
+	struct file *file, loff_t start, size_t len, struct mempolicy *mpol)
+{
+	struct restrictedmem *rm;
+	unsigned long end;
+
+	if (!PAGE_ALIGNED(start))
+		return -EINVAL;
+
+	len = PAGE_ALIGN(len);
+	end = start + len;
+
+	if (end < start)
+		return -EINVAL;
+	if (end == start)
+		return 0;
+
+	rm = file->f_mapping->private_data;
+	return __mpol_set_shared_policy(shmem_shared_policy(rm->memfd), mpol,
+					start >> PAGE_SHIFT, len >> PAGE_SHIFT);
+}
+
+static long do_memfd_restricted_bind(
+	int fd, loff_t offset, size_t len,
+	unsigned long mode, const unsigned long __user *nmask,
+	unsigned long maxnode, unsigned int flags)
+{
+	long ret;
+	struct fd f;
+	struct mempolicy *mpol;
+
+	/* None of the flags are supported */
+	if (flags)
+		return -EINVAL;
+
+	f = fdget_raw(fd);
+	if (!f.file)
+		return -EBADF;
+
+	if (!file_is_restrictedmem(f.file))
+		return -EINVAL;
+
+	mpol = mpol_create(mode, nmask, maxnode);
+	if (IS_ERR(mpol)) {
+		ret = PTR_ERR(mpol);
+		goto out;
+	}
+
+	ret = restrictedmem_set_shared_policy(f.file, offset, len, mpol);
+
+	mpol_put(mpol);
+
+out:
+	fdput(f);
+
+	return ret;
+}
+
+SYSCALL_DEFINE6(memfd_restricted_bind, int, fd, struct file_range __user *, range,
+		unsigned long, mode, const unsigned long __user *, nmask,
+		unsigned long, maxnode, unsigned int, flags)
+{
+	loff_t offset;
+	size_t len;
+
+	if (unlikely(get_user(offset, &range->offset)))
+		return -EFAULT;
+	if (unlikely(get_user(len, &range->len)))
+		return -EFAULT;
+
+	return do_memfd_restricted_bind(fd, offset, len, mode, nmask,
+					    maxnode, flags);
+}
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index 3c4d2508226a..e253529cf1ec 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -46,6 +46,7 @@ cat << EOF
 
 #ifndef __ARCH_WANT_MEMFD_RESTRICTED
 #define __IGNORE_memfd_restricted
+#define __IGNORE_memfd_restricted_bind
 #endif
 
 /* Missing flags argument */
