diff mbox series

[v13,2/4] fs: add LSM-supporting anon-inode interface

Message ID 20201112015359.1103333-3-lokeshgidra@google.com (mailing list archive)
State New, archived
Headers show
Series SELinux support for anonymous inodes and UFFD | expand

Commit Message

Lokesh Gidra Nov. 12, 2020, 1:53 a.m. UTC
From: Daniel Colascione <dancol@google.com>

This change adds a new function, anon_inode_getfd_secure, that creates
anonymous-node file with individual non-S_PRIVATE inode to which security
modules can apply policy. Existing callers continue using the original
singleton-inode kind of anonymous-inode file. We can transition anonymous
inode users to the new kind of anonymous inode in individual patches for
the sake of bisection and review.

The new function accepts an optional context_inode parameter that callers
can use to provide additional contextual information to security modules.
For example, in case of userfaultfd, the created inode is a 'logical child'
of the context_inode (userfaultfd inode of the parent process) in the sense
that it provides the security context required during creation of the child
process' userfaultfd inode.

Signed-off-by: Daniel Colascione <dancol@google.com>

[Delete obsolete comments to alloc_anon_inode()]
[Add context_inode description in comments to anon_inode_getfd_secure()]
[Remove definition of anon_inode_getfile_secure() as there are no callers]
[Make __anon_inode_getfile() static]
[Use correct error cast in __anon_inode_getfile()]
[Fix error handling in __anon_inode_getfile()]

Signed-off-by: Lokesh Gidra <lokeshgidra@google.com>
Reviewed-by: Eric Biggers <ebiggers@google.com>
---
 fs/anon_inodes.c            | 150 ++++++++++++++++++++++++++----------
 fs/libfs.c                  |   5 --
 include/linux/anon_inodes.h |   5 ++
 3 files changed, 115 insertions(+), 45 deletions(-)

Comments

Paul Moore Jan. 7, 2021, 2:09 a.m. UTC | #1
On Wed, Nov 11, 2020 at 8:54 PM Lokesh Gidra <lokeshgidra@google.com> wrote:
> From: Daniel Colascione <dancol@google.com>
>
> This change adds a new function, anon_inode_getfd_secure, that creates
> anonymous-node file with individual non-S_PRIVATE inode to which security
> modules can apply policy. Existing callers continue using the original
> singleton-inode kind of anonymous-inode file. We can transition anonymous
> inode users to the new kind of anonymous inode in individual patches for
> the sake of bisection and review.
>
> The new function accepts an optional context_inode parameter that callers
> can use to provide additional contextual information to security modules.
> For example, in case of userfaultfd, the created inode is a 'logical child'
> of the context_inode (userfaultfd inode of the parent process) in the sense
> that it provides the security context required during creation of the child
> process' userfaultfd inode.
>
> Signed-off-by: Daniel Colascione <dancol@google.com>
>
> [Delete obsolete comments to alloc_anon_inode()]
> [Add context_inode description in comments to anon_inode_getfd_secure()]
> [Remove definition of anon_inode_getfile_secure() as there are no callers]
> [Make __anon_inode_getfile() static]
> [Use correct error cast in __anon_inode_getfile()]
> [Fix error handling in __anon_inode_getfile()]

Lokesh, I'm assuming you made the changes in the brackets above?  If
so they should include your initials or some other means of
attributing them to you, e.g. "[LG: Fix error ...]".

> Signed-off-by: Lokesh Gidra <lokeshgidra@google.com>
> Reviewed-by: Eric Biggers <ebiggers@google.com>
> ---
>  fs/anon_inodes.c            | 150 ++++++++++++++++++++++++++----------
>  fs/libfs.c                  |   5 --
>  include/linux/anon_inodes.h |   5 ++
>  3 files changed, 115 insertions(+), 45 deletions(-)
>
> diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
> index 89714308c25b..023337d65a03 100644
> --- a/fs/anon_inodes.c
> +++ b/fs/anon_inodes.c
> @@ -55,61 +55,79 @@ static struct file_system_type anon_inode_fs_type = {
>         .kill_sb        = kill_anon_super,
>  };
>
> -/**
> - * anon_inode_getfile - creates a new file instance by hooking it up to an
> - *                      anonymous inode, and a dentry that describe the "class"
> - *                      of the file
> - *
> - * @name:    [in]    name of the "class" of the new file
> - * @fops:    [in]    file operations for the new file
> - * @priv:    [in]    private data for the new file (will be file's private_data)
> - * @flags:   [in]    flags
> - *
> - * Creates a new file by hooking it on a single inode. This is useful for files
> - * that do not need to have a full-fledged inode in order to operate correctly.
> - * All the files created with anon_inode_getfile() will share a single inode,
> - * hence saving memory and avoiding code duplication for the file/inode/dentry
> - * setup.  Returns the newly created file* or an error pointer.
> - */
> -struct file *anon_inode_getfile(const char *name,
> -                               const struct file_operations *fops,
> -                               void *priv, int flags)
> +static struct inode *anon_inode_make_secure_inode(
> +       const char *name,
> +       const struct inode *context_inode)
>  {
> -       struct file *file;
> +       struct inode *inode;
> +       const struct qstr qname = QSTR_INIT(name, strlen(name));
> +       int error;
> +
> +       inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
> +       if (IS_ERR(inode))
> +               return inode;
> +       inode->i_flags &= ~S_PRIVATE;
> +       error = security_inode_init_security_anon(inode, &qname, context_inode);
> +       if (error) {
> +               iput(inode);
> +               return ERR_PTR(error);
> +       }
> +       return inode;
> +}
>
> -       if (IS_ERR(anon_inode_inode))
> -               return ERR_PTR(-ENODEV);
> +static struct file *__anon_inode_getfile(const char *name,
> +                                        const struct file_operations *fops,
> +                                        void *priv, int flags,
> +                                        const struct inode *context_inode,
> +                                        bool secure)

Is it necessary to pass both the context_inode pointer and the secure
boolean?  It seems like if context_inode is non-NULL then one could
assume that a secure anonymous inode was requested; is there ever
going to be a case where this is not true?

> +{
> +       struct inode *inode;
> +       struct file *file;
>
>         if (fops->owner && !try_module_get(fops->owner))
>                 return ERR_PTR(-ENOENT);
>
> -       /*
> -        * We know the anon_inode inode count is always greater than zero,
> -        * so ihold() is safe.
> -        */
> -       ihold(anon_inode_inode);
> -       file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name,
> +       if (secure) {
> +               inode = anon_inode_make_secure_inode(name, context_inode);
> +               if (IS_ERR(inode)) {
> +                       file = ERR_CAST(inode);
> +                       goto err;
> +               }
> +       } else {
> +               inode = anon_inode_inode;
> +               if (IS_ERR(inode)) {
> +                       file = ERR_PTR(-ENODEV);
> +                       goto err;
> +               }
> +               /*
> +                * We know the anon_inode inode count is always
> +                * greater than zero, so ihold() is safe.
> +                */
> +               ihold(inode);
> +       }
> +
> +       file = alloc_file_pseudo(inode, anon_inode_mnt, name,
>                                  flags & (O_ACCMODE | O_NONBLOCK), fops);
>         if (IS_ERR(file))
> -               goto err;
> +               goto err_iput;
>
> -       file->f_mapping = anon_inode_inode->i_mapping;
> +       file->f_mapping = inode->i_mapping;
>
>         file->private_data = priv;
>
>         return file;
>
> +err_iput:
> +       iput(inode);
>  err:
> -       iput(anon_inode_inode);
>         module_put(fops->owner);
>         return file;
>  }
> -EXPORT_SYMBOL_GPL(anon_inode_getfile);

--
paul moore
www.paul-moore.com
dancol Jan. 7, 2021, 2:42 a.m. UTC | #2
On 2021-01-06 21:09, Paul Moore wrote:
> Is it necessary to pass both the context_inode pointer and the secure
> boolean?  It seems like if context_inode is non-NULL then one could
> assume that a secure anonymous inode was requested; is there ever
> going to be a case where this is not true?

The converse isn't true though: it makes sense to ask for a secure inode 
with a NULL context inode.
Lokesh Gidra Jan. 7, 2021, 2:43 a.m. UTC | #3
On Wed, Jan 6, 2021 at 6:10 PM Paul Moore <paul@paul-moore.com> wrote:
>
> On Wed, Nov 11, 2020 at 8:54 PM Lokesh Gidra <lokeshgidra@google.com> wrote:
> > From: Daniel Colascione <dancol@google.com>
> >
> > This change adds a new function, anon_inode_getfd_secure, that creates
> > anonymous-node file with individual non-S_PRIVATE inode to which security
> > modules can apply policy. Existing callers continue using the original
> > singleton-inode kind of anonymous-inode file. We can transition anonymous
> > inode users to the new kind of anonymous inode in individual patches for
> > the sake of bisection and review.
> >
> > The new function accepts an optional context_inode parameter that callers
> > can use to provide additional contextual information to security modules.
> > For example, in case of userfaultfd, the created inode is a 'logical child'
> > of the context_inode (userfaultfd inode of the parent process) in the sense
> > that it provides the security context required during creation of the child
> > process' userfaultfd inode.
> >
> > Signed-off-by: Daniel Colascione <dancol@google.com>
> >
> > [Delete obsolete comments to alloc_anon_inode()]
> > [Add context_inode description in comments to anon_inode_getfd_secure()]
> > [Remove definition of anon_inode_getfile_secure() as there are no callers]
> > [Make __anon_inode_getfile() static]
> > [Use correct error cast in __anon_inode_getfile()]
> > [Fix error handling in __anon_inode_getfile()]
>
> Lokesh, I'm assuming you made the changes in the brackets above?  If
> so they should include your initials or some other means of
> attributing them to you, e.g. "[LG: Fix error ...]".

Thanks for reviewing the patch. Sorry for missing this. If it's
critical then I can upload another version of the patches to fix this.
Kindly let me know.
>
> > Signed-off-by: Lokesh Gidra <lokeshgidra@google.com>
> > Reviewed-by: Eric Biggers <ebiggers@google.com>
> > ---
> >  fs/anon_inodes.c            | 150 ++++++++++++++++++++++++++----------
> >  fs/libfs.c                  |   5 --
> >  include/linux/anon_inodes.h |   5 ++
> >  3 files changed, 115 insertions(+), 45 deletions(-)
> >
> > diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
> > index 89714308c25b..023337d65a03 100644
> > --- a/fs/anon_inodes.c
> > +++ b/fs/anon_inodes.c
> > @@ -55,61 +55,79 @@ static struct file_system_type anon_inode_fs_type = {
> >         .kill_sb        = kill_anon_super,
> >  };
> >
> > -/**
> > - * anon_inode_getfile - creates a new file instance by hooking it up to an
> > - *                      anonymous inode, and a dentry that describe the "class"
> > - *                      of the file
> > - *
> > - * @name:    [in]    name of the "class" of the new file
> > - * @fops:    [in]    file operations for the new file
> > - * @priv:    [in]    private data for the new file (will be file's private_data)
> > - * @flags:   [in]    flags
> > - *
> > - * Creates a new file by hooking it on a single inode. This is useful for files
> > - * that do not need to have a full-fledged inode in order to operate correctly.
> > - * All the files created with anon_inode_getfile() will share a single inode,
> > - * hence saving memory and avoiding code duplication for the file/inode/dentry
> > - * setup.  Returns the newly created file* or an error pointer.
> > - */
> > -struct file *anon_inode_getfile(const char *name,
> > -                               const struct file_operations *fops,
> > -                               void *priv, int flags)
> > +static struct inode *anon_inode_make_secure_inode(
> > +       const char *name,
> > +       const struct inode *context_inode)
> >  {
> > -       struct file *file;
> > +       struct inode *inode;
> > +       const struct qstr qname = QSTR_INIT(name, strlen(name));
> > +       int error;
> > +
> > +       inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
> > +       if (IS_ERR(inode))
> > +               return inode;
> > +       inode->i_flags &= ~S_PRIVATE;
> > +       error = security_inode_init_security_anon(inode, &qname, context_inode);
> > +       if (error) {
> > +               iput(inode);
> > +               return ERR_PTR(error);
> > +       }
> > +       return inode;
> > +}
> >
> > -       if (IS_ERR(anon_inode_inode))
> > -               return ERR_PTR(-ENODEV);
> > +static struct file *__anon_inode_getfile(const char *name,
> > +                                        const struct file_operations *fops,
> > +                                        void *priv, int flags,
> > +                                        const struct inode *context_inode,
> > +                                        bool secure)
>
> Is it necessary to pass both the context_inode pointer and the secure
> boolean?  It seems like if context_inode is non-NULL then one could
> assume that a secure anonymous inode was requested; is there ever
> going to be a case where this is not true?

Yes, it is necessary as there are scenarios where a secure anon-inode
is to be created but there is no context_inode available. For
instance, in patch 4/4 of this series you'll see that when a secure
anon-inode is created in the userfaultfd syscall, context_inode isn't
available.
>
> > +{
> > +       struct inode *inode;
> > +       struct file *file;
> >
> >         if (fops->owner && !try_module_get(fops->owner))
> >                 return ERR_PTR(-ENOENT);
> >
> > -       /*
> > -        * We know the anon_inode inode count is always greater than zero,
> > -        * so ihold() is safe.
> > -        */
> > -       ihold(anon_inode_inode);
> > -       file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name,
> > +       if (secure) {
> > +               inode = anon_inode_make_secure_inode(name, context_inode);
> > +               if (IS_ERR(inode)) {
> > +                       file = ERR_CAST(inode);
> > +                       goto err;
> > +               }
> > +       } else {
> > +               inode = anon_inode_inode;
> > +               if (IS_ERR(inode)) {
> > +                       file = ERR_PTR(-ENODEV);
> > +                       goto err;
> > +               }
> > +               /*
> > +                * We know the anon_inode inode count is always
> > +                * greater than zero, so ihold() is safe.
> > +                */
> > +               ihold(inode);
> > +       }
> > +
> > +       file = alloc_file_pseudo(inode, anon_inode_mnt, name,
> >                                  flags & (O_ACCMODE | O_NONBLOCK), fops);
> >         if (IS_ERR(file))
> > -               goto err;
> > +               goto err_iput;
> >
> > -       file->f_mapping = anon_inode_inode->i_mapping;
> > +       file->f_mapping = inode->i_mapping;
> >
> >         file->private_data = priv;
> >
> >         return file;
> >
> > +err_iput:
> > +       iput(inode);
> >  err:
> > -       iput(anon_inode_inode);
> >         module_put(fops->owner);
> >         return file;
> >  }
> > -EXPORT_SYMBOL_GPL(anon_inode_getfile);
>
> --
> paul moore
> www.paul-moore.com
Paul Moore Jan. 7, 2021, 3:05 a.m. UTC | #4
On Wed, Jan 6, 2021 at 9:42 PM dancol <dancol@dancol.org> wrote:
>
> On 2021-01-06 21:09, Paul Moore wrote:
> > Is it necessary to pass both the context_inode pointer and the secure
> > boolean?  It seems like if context_inode is non-NULL then one could
> > assume that a secure anonymous inode was requested; is there ever
> > going to be a case where this is not true?
>
> The converse isn't true though: it makes sense to ask for a secure inode
> with a NULL context inode.

Having looked at patch 3/4 and 4/4 I just realized that and was coming
back to update my comments :)
Paul Moore Jan. 7, 2021, 3:08 a.m. UTC | #5
On Wed, Jan 6, 2021 at 9:44 PM Lokesh Gidra <lokeshgidra@google.com> wrote:
> On Wed, Jan 6, 2021 at 6:10 PM Paul Moore <paul@paul-moore.com> wrote:
> >
> > On Wed, Nov 11, 2020 at 8:54 PM Lokesh Gidra <lokeshgidra@google.com> wrote:
> > > From: Daniel Colascione <dancol@google.com>
> > >
> > > This change adds a new function, anon_inode_getfd_secure, that creates
> > > anonymous-node file with individual non-S_PRIVATE inode to which security
> > > modules can apply policy. Existing callers continue using the original
> > > singleton-inode kind of anonymous-inode file. We can transition anonymous
> > > inode users to the new kind of anonymous inode in individual patches for
> > > the sake of bisection and review.
> > >
> > > The new function accepts an optional context_inode parameter that callers
> > > can use to provide additional contextual information to security modules.
> > > For example, in case of userfaultfd, the created inode is a 'logical child'
> > > of the context_inode (userfaultfd inode of the parent process) in the sense
> > > that it provides the security context required during creation of the child
> > > process' userfaultfd inode.
> > >
> > > Signed-off-by: Daniel Colascione <dancol@google.com>
> > >
> > > [Delete obsolete comments to alloc_anon_inode()]
> > > [Add context_inode description in comments to anon_inode_getfd_secure()]
> > > [Remove definition of anon_inode_getfile_secure() as there are no callers]
> > > [Make __anon_inode_getfile() static]
> > > [Use correct error cast in __anon_inode_getfile()]
> > > [Fix error handling in __anon_inode_getfile()]
> >
> > Lokesh, I'm assuming you made the changes in the brackets above?  If
> > so they should include your initials or some other means of
> > attributing them to you, e.g. "[LG: Fix error ...]".
>
> Thanks for reviewing the patch. Sorry for missing this. If it's
> critical then I can upload another version of the patches to fix this.
> Kindly let me know.

Normally that is something I could fix during a merge with your
approval, but see my comments to patch 3/4; I think this patchset
still needs some work.

> > > Signed-off-by: Lokesh Gidra <lokeshgidra@google.com>
> > > Reviewed-by: Eric Biggers <ebiggers@google.com>
> > > ---
> > >  fs/anon_inodes.c            | 150 ++++++++++++++++++++++++++----------
> > >  fs/libfs.c                  |   5 --
> > >  include/linux/anon_inodes.h |   5 ++
> > >  3 files changed, 115 insertions(+), 45 deletions(-)

...

> > > +static struct file *__anon_inode_getfile(const char *name,
> > > +                                        const struct file_operations *fops,
> > > +                                        void *priv, int flags,
> > > +                                        const struct inode *context_inode,
> > > +                                        bool secure)
> >
> > Is it necessary to pass both the context_inode pointer and the secure
> > boolean?  It seems like if context_inode is non-NULL then one could
> > assume that a secure anonymous inode was requested; is there ever
> > going to be a case where this is not true?
>
> Yes, it is necessary as there are scenarios where a secure anon-inode
> is to be created but there is no context_inode available. For
> instance, in patch 4/4 of this series you'll see that when a secure
> anon-inode is created in the userfaultfd syscall, context_inode isn't
> available.

My mistake, I didn't realize this until I got further in the patchset.
diff mbox series

Patch

diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 89714308c25b..023337d65a03 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -55,61 +55,79 @@  static struct file_system_type anon_inode_fs_type = {
 	.kill_sb	= kill_anon_super,
 };
 
-/**
- * anon_inode_getfile - creates a new file instance by hooking it up to an
- *                      anonymous inode, and a dentry that describe the "class"
- *                      of the file
- *
- * @name:    [in]    name of the "class" of the new file
- * @fops:    [in]    file operations for the new file
- * @priv:    [in]    private data for the new file (will be file's private_data)
- * @flags:   [in]    flags
- *
- * Creates a new file by hooking it on a single inode. This is useful for files
- * that do not need to have a full-fledged inode in order to operate correctly.
- * All the files created with anon_inode_getfile() will share a single inode,
- * hence saving memory and avoiding code duplication for the file/inode/dentry
- * setup.  Returns the newly created file* or an error pointer.
- */
-struct file *anon_inode_getfile(const char *name,
-				const struct file_operations *fops,
-				void *priv, int flags)
+static struct inode *anon_inode_make_secure_inode(
+	const char *name,
+	const struct inode *context_inode)
 {
-	struct file *file;
+	struct inode *inode;
+	const struct qstr qname = QSTR_INIT(name, strlen(name));
+	int error;
+
+	inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
+	if (IS_ERR(inode))
+		return inode;
+	inode->i_flags &= ~S_PRIVATE;
+	error =	security_inode_init_security_anon(inode, &qname, context_inode);
+	if (error) {
+		iput(inode);
+		return ERR_PTR(error);
+	}
+	return inode;
+}
 
-	if (IS_ERR(anon_inode_inode))
-		return ERR_PTR(-ENODEV);
+static struct file *__anon_inode_getfile(const char *name,
+					 const struct file_operations *fops,
+					 void *priv, int flags,
+					 const struct inode *context_inode,
+					 bool secure)
+{
+	struct inode *inode;
+	struct file *file;
 
 	if (fops->owner && !try_module_get(fops->owner))
 		return ERR_PTR(-ENOENT);
 
-	/*
-	 * We know the anon_inode inode count is always greater than zero,
-	 * so ihold() is safe.
-	 */
-	ihold(anon_inode_inode);
-	file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name,
+	if (secure) {
+		inode =	anon_inode_make_secure_inode(name, context_inode);
+		if (IS_ERR(inode)) {
+			file = ERR_CAST(inode);
+			goto err;
+		}
+	} else {
+		inode =	anon_inode_inode;
+		if (IS_ERR(inode)) {
+			file = ERR_PTR(-ENODEV);
+			goto err;
+		}
+		/*
+		 * We know the anon_inode inode count is always
+		 * greater than zero, so ihold() is safe.
+		 */
+		ihold(inode);
+	}
+
+	file = alloc_file_pseudo(inode, anon_inode_mnt, name,
 				 flags & (O_ACCMODE | O_NONBLOCK), fops);
 	if (IS_ERR(file))
-		goto err;
+		goto err_iput;
 
-	file->f_mapping = anon_inode_inode->i_mapping;
+	file->f_mapping = inode->i_mapping;
 
 	file->private_data = priv;
 
 	return file;
 
+err_iput:
+	iput(inode);
 err:
-	iput(anon_inode_inode);
 	module_put(fops->owner);
 	return file;
 }
-EXPORT_SYMBOL_GPL(anon_inode_getfile);
 
 /**
- * anon_inode_getfd - creates a new file instance by hooking it up to an
- *                    anonymous inode, and a dentry that describe the "class"
- *                    of the file
+ * anon_inode_getfile - creates a new file instance by hooking it up to an
+ *                      anonymous inode, and a dentry that describe the "class"
+ *                      of the file
  *
  * @name:    [in]    name of the "class" of the new file
  * @fops:    [in]    file operations for the new file
@@ -118,12 +136,23 @@  EXPORT_SYMBOL_GPL(anon_inode_getfile);
  *
  * Creates a new file by hooking it on a single inode. This is useful for files
  * that do not need to have a full-fledged inode in order to operate correctly.
- * All the files created with anon_inode_getfd() will share a single inode,
+ * All the files created with anon_inode_getfile() will share a single inode,
  * hence saving memory and avoiding code duplication for the file/inode/dentry
- * setup.  Returns new descriptor or an error code.
+ * setup.  Returns the newly created file* or an error pointer.
  */
-int anon_inode_getfd(const char *name, const struct file_operations *fops,
-		     void *priv, int flags)
+struct file *anon_inode_getfile(const char *name,
+				const struct file_operations *fops,
+				void *priv, int flags)
+{
+	return __anon_inode_getfile(name, fops, priv, flags, NULL, false);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfile);
+
+static int __anon_inode_getfd(const char *name,
+			      const struct file_operations *fops,
+			      void *priv, int flags,
+			      const struct inode *context_inode,
+			      bool secure)
 {
 	int error, fd;
 	struct file *file;
@@ -133,7 +162,8 @@  int anon_inode_getfd(const char *name, const struct file_operations *fops,
 		return error;
 	fd = error;
 
-	file = anon_inode_getfile(name, fops, priv, flags);
+	file = __anon_inode_getfile(name, fops, priv, flags, context_inode,
+				    secure);
 	if (IS_ERR(file)) {
 		error = PTR_ERR(file);
 		goto err_put_unused_fd;
@@ -146,8 +176,48 @@  int anon_inode_getfd(const char *name, const struct file_operations *fops,
 	put_unused_fd(fd);
 	return error;
 }
+
+/**
+ * anon_inode_getfd - creates a new file instance by hooking it up to
+ *                    an anonymous inode and a dentry that describe
+ *                    the "class" of the file
+ *
+ * @name:    [in]    name of the "class" of the new file
+ * @fops:    [in]    file operations for the new file
+ * @priv:    [in]    private data for the new file (will be file's private_data)
+ * @flags:   [in]    flags
+ *
+ * Creates a new file by hooking it on a single inode. This is
+ * useful for files that do not need to have a full-fledged inode in
+ * order to operate correctly.  All the files created with
+ * anon_inode_getfd() will use the same singleton inode, reducing
+ * memory use and avoiding code duplication for the file/inode/dentry
+ * setup.  Returns a newly created file descriptor or an error code.
+ */
+int anon_inode_getfd(const char *name, const struct file_operations *fops,
+		     void *priv, int flags)
+{
+	return __anon_inode_getfd(name, fops, priv, flags, NULL, false);
+}
 EXPORT_SYMBOL_GPL(anon_inode_getfd);
 
+/**
+ * Like anon_inode_getfd(), but creates a new !S_PRIVATE anon inode rather than
+ * reuse the singleton anon inode, and calls the inode_init_security_anon() LSM
+ * hook. This allows the inode to have its own security context and for a LSM
+ * to reject creation of the inode.  An optional @context_inode argument is
+ * also added to provide the logical relationship with the new inode.  The LSM
+ * may use @context_inode in inode_init_security_anon(), but a reference to it
+ * is not held.
+ */
+int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode)
+{
+	return __anon_inode_getfd(name, fops, priv, flags, context_inode, true);
+}
+EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
+
 static int __init anon_inode_init(void)
 {
 	anon_inode_mnt = kern_mount(&anon_inode_fs_type);
diff --git a/fs/libfs.c b/fs/libfs.c
index fc34361c1489..51c19c72e563 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -1212,11 +1212,6 @@  static int anon_set_page_dirty(struct page *page)
 	return 0;
 };
 
-/*
- * A single inode exists for all anon_inode files. Contrary to pipes,
- * anon_inode inodes have no associated per-instance data, so we need
- * only allocate one of them.
- */
 struct inode *alloc_anon_inode(struct super_block *s)
 {
 	static const struct address_space_operations anon_aops = {
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
index d0d7d96261ad..71881a2b6f78 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -10,12 +10,17 @@ 
 #define _LINUX_ANON_INODES_H
 
 struct file_operations;
+struct inode;
 
 struct file *anon_inode_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags);
 int anon_inode_getfd(const char *name, const struct file_operations *fops,
 		     void *priv, int flags);
+int anon_inode_getfd_secure(const char *name,
+			    const struct file_operations *fops,
+			    void *priv, int flags,
+			    const struct inode *context_inode);
 
 #endif /* _LINUX_ANON_INODES_H */