Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs: add LSM-supporting anon-inode interface

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>
[LG: Delete obsolete comments to alloc_anon_inode()]
[LG: Add context_inode description in comments to anon_inode_getfd_secure()]
[LG: Remove definition of anon_inode_getfile_secure() as there are no callers]
[LG: Make __anon_inode_getfile() static]
[LG: Use correct error cast in __anon_inode_getfile()]
[LG: Fix error handling in __anon_inode_getfile()]
Signed-off-by: Lokesh Gidra <lokeshgidra@google.com>
Reviewed-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Daniel Colascione and committed by
Paul Moore
e7e832ce 215b674b

+122 -52
+117 -47
fs/anon_inodes.c
··· 55 55 .kill_sb = kill_anon_super, 56 56 }; 57 57 58 + static struct inode *anon_inode_make_secure_inode( 59 + const char *name, 60 + const struct inode *context_inode) 61 + { 62 + struct inode *inode; 63 + const struct qstr qname = QSTR_INIT(name, strlen(name)); 64 + int error; 65 + 66 + inode = alloc_anon_inode(anon_inode_mnt->mnt_sb); 67 + if (IS_ERR(inode)) 68 + return inode; 69 + inode->i_flags &= ~S_PRIVATE; 70 + error = security_inode_init_security_anon(inode, &qname, context_inode); 71 + if (error) { 72 + iput(inode); 73 + return ERR_PTR(error); 74 + } 75 + return inode; 76 + } 77 + 78 + static struct file *__anon_inode_getfile(const char *name, 79 + const struct file_operations *fops, 80 + void *priv, int flags, 81 + const struct inode *context_inode, 82 + bool secure) 83 + { 84 + struct inode *inode; 85 + struct file *file; 86 + 87 + if (fops->owner && !try_module_get(fops->owner)) 88 + return ERR_PTR(-ENOENT); 89 + 90 + if (secure) { 91 + inode = anon_inode_make_secure_inode(name, context_inode); 92 + if (IS_ERR(inode)) { 93 + file = ERR_CAST(inode); 94 + goto err; 95 + } 96 + } else { 97 + inode = anon_inode_inode; 98 + if (IS_ERR(inode)) { 99 + file = ERR_PTR(-ENODEV); 100 + goto err; 101 + } 102 + /* 103 + * We know the anon_inode inode count is always 104 + * greater than zero, so ihold() is safe. 105 + */ 106 + ihold(inode); 107 + } 108 + 109 + file = alloc_file_pseudo(inode, anon_inode_mnt, name, 110 + flags & (O_ACCMODE | O_NONBLOCK), fops); 111 + if (IS_ERR(file)) 112 + goto err_iput; 113 + 114 + file->f_mapping = inode->i_mapping; 115 + 116 + file->private_data = priv; 117 + 118 + return file; 119 + 120 + err_iput: 121 + iput(inode); 122 + err: 123 + module_put(fops->owner); 124 + return file; 125 + } 126 + 58 127 /** 59 128 * anon_inode_getfile - creates a new file instance by hooking it up to an 60 129 * anonymous inode, and a dentry that describe the "class" ··· 144 75 const struct file_operations *fops, 145 76 void *priv, int flags) 146 77 { 147 - struct file *file; 148 - 149 - if (IS_ERR(anon_inode_inode)) 150 - return ERR_PTR(-ENODEV); 151 - 152 - if (fops->owner && !try_module_get(fops->owner)) 153 - return ERR_PTR(-ENOENT); 154 - 155 - /* 156 - * We know the anon_inode inode count is always greater than zero, 157 - * so ihold() is safe. 158 - */ 159 - ihold(anon_inode_inode); 160 - file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name, 161 - flags & (O_ACCMODE | O_NONBLOCK), fops); 162 - if (IS_ERR(file)) 163 - goto err; 164 - 165 - file->f_mapping = anon_inode_inode->i_mapping; 166 - 167 - file->private_data = priv; 168 - 169 - return file; 170 - 171 - err: 172 - iput(anon_inode_inode); 173 - module_put(fops->owner); 174 - return file; 78 + return __anon_inode_getfile(name, fops, priv, flags, NULL, false); 175 79 } 176 80 EXPORT_SYMBOL_GPL(anon_inode_getfile); 177 81 178 - /** 179 - * anon_inode_getfd - creates a new file instance by hooking it up to an 180 - * anonymous inode, and a dentry that describe the "class" 181 - * of the file 182 - * 183 - * @name: [in] name of the "class" of the new file 184 - * @fops: [in] file operations for the new file 185 - * @priv: [in] private data for the new file (will be file's private_data) 186 - * @flags: [in] flags 187 - * 188 - * Creates a new file by hooking it on a single inode. This is useful for files 189 - * that do not need to have a full-fledged inode in order to operate correctly. 190 - * All the files created with anon_inode_getfd() will share a single inode, 191 - * hence saving memory and avoiding code duplication for the file/inode/dentry 192 - * setup. Returns new descriptor or an error code. 193 - */ 194 - int anon_inode_getfd(const char *name, const struct file_operations *fops, 195 - void *priv, int flags) 82 + static int __anon_inode_getfd(const char *name, 83 + const struct file_operations *fops, 84 + void *priv, int flags, 85 + const struct inode *context_inode, 86 + bool secure) 196 87 { 197 88 int error, fd; 198 89 struct file *file; ··· 162 133 return error; 163 134 fd = error; 164 135 165 - file = anon_inode_getfile(name, fops, priv, flags); 136 + file = __anon_inode_getfile(name, fops, priv, flags, context_inode, 137 + secure); 166 138 if (IS_ERR(file)) { 167 139 error = PTR_ERR(file); 168 140 goto err_put_unused_fd; ··· 176 146 put_unused_fd(fd); 177 147 return error; 178 148 } 149 + 150 + /** 151 + * anon_inode_getfd - creates a new file instance by hooking it up to 152 + * an anonymous inode and a dentry that describe 153 + * the "class" of the file 154 + * 155 + * @name: [in] name of the "class" of the new file 156 + * @fops: [in] file operations for the new file 157 + * @priv: [in] private data for the new file (will be file's private_data) 158 + * @flags: [in] flags 159 + * 160 + * Creates a new file by hooking it on a single inode. This is 161 + * useful for files that do not need to have a full-fledged inode in 162 + * order to operate correctly. All the files created with 163 + * anon_inode_getfd() will use the same singleton inode, reducing 164 + * memory use and avoiding code duplication for the file/inode/dentry 165 + * setup. Returns a newly created file descriptor or an error code. 166 + */ 167 + int anon_inode_getfd(const char *name, const struct file_operations *fops, 168 + void *priv, int flags) 169 + { 170 + return __anon_inode_getfd(name, fops, priv, flags, NULL, false); 171 + } 179 172 EXPORT_SYMBOL_GPL(anon_inode_getfd); 173 + 174 + /** 175 + * Like anon_inode_getfd(), but creates a new !S_PRIVATE anon inode rather than 176 + * reuse the singleton anon inode, and calls the inode_init_security_anon() LSM 177 + * hook. This allows the inode to have its own security context and for a LSM 178 + * to reject creation of the inode. An optional @context_inode argument is 179 + * also added to provide the logical relationship with the new inode. The LSM 180 + * may use @context_inode in inode_init_security_anon(), but a reference to it 181 + * is not held. 182 + */ 183 + int anon_inode_getfd_secure(const char *name, const struct file_operations *fops, 184 + void *priv, int flags, 185 + const struct inode *context_inode) 186 + { 187 + return __anon_inode_getfd(name, fops, priv, flags, context_inode, true); 188 + } 189 + EXPORT_SYMBOL_GPL(anon_inode_getfd_secure); 180 190 181 191 static int __init anon_inode_init(void) 182 192 {
-5
fs/libfs.c
··· 1214 1214 return 0; 1215 1215 }; 1216 1216 1217 - /* 1218 - * A single inode exists for all anon_inode files. Contrary to pipes, 1219 - * anon_inode inodes have no associated per-instance data, so we need 1220 - * only allocate one of them. 1221 - */ 1222 1217 struct inode *alloc_anon_inode(struct super_block *s) 1223 1218 { 1224 1219 static const struct address_space_operations anon_aops = {
+5
include/linux/anon_inodes.h
··· 10 10 #define _LINUX_ANON_INODES_H 11 11 12 12 struct file_operations; 13 + struct inode; 13 14 14 15 struct file *anon_inode_getfile(const char *name, 15 16 const struct file_operations *fops, 16 17 void *priv, int flags); 17 18 int anon_inode_getfd(const char *name, const struct file_operations *fops, 18 19 void *priv, int flags); 20 + int anon_inode_getfd_secure(const char *name, 21 + const struct file_operations *fops, 22 + void *priv, int flags, 23 + const struct inode *context_inode); 19 24 20 25 #endif /* _LINUX_ANON_INODES_H */ 21 26