xref: /linux/fs/failfs.c (revision fa0d6d945e5ce96cff14b114eec7527f13d7f23a)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2026 Christian Brauner <brauner@kernel.org> */
3 #include <linux/fs.h>
4 #include <linux/fs/super_types.h>
5 #include <linux/fs_context.h>
6 #include <linux/magic.h>
7 #include <linux/mount.h>
8 
9 #include "internal.h"
10 
11 static struct path failfs_root_path = {};
12 
13 void failfs_get_root(struct path *path)
14 {
15 	*path = failfs_root_path;
16 	path_get(path);
17 }
18 
19 bool failfs_mnt(const struct vfsmount *mnt)
20 {
21 	return mnt->mnt_sb == failfs_root_path.mnt->mnt_sb;
22 }
23 
24 static int failfs_permission(struct mnt_idmap *idmap, struct inode *inode,
25 			     int mask)
26 {
27 	return -EOPNOTSUPP;
28 }
29 
30 static struct dentry *failfs_lookup(struct inode *dir, struct dentry *dentry,
31 				    unsigned int flags)
32 {
33 	/* Unreachable: ->permission() already failed the walk. */
34 	return ERR_PTR(-EOPNOTSUPP);
35 }
36 
37 static int failfs_getattr(struct mnt_idmap *idmap, const struct path *path,
38 			  struct kstat *stat, u32 request_mask,
39 			  unsigned int query_flags)
40 {
41 	return -EOPNOTSUPP;
42 }
43 
44 static const struct inode_operations failfs_dir_inode_operations = {
45 	.permission	= failfs_permission,
46 	.lookup		= failfs_lookup,
47 	.getattr	= failfs_getattr,
48 };
49 
50 static const struct file_operations failfs_dir_operations = {};
51 
52 static int failfs_d_weak_revalidate(struct dentry *dentry, unsigned int flags)
53 {
54 	/*
55 	 * The root is only ever reached as a path-walk terminal by jumping
56 	 * to it: as "/" when it is the caller's root, or through a
57 	 * /proc/<pid>/{root,cwd} magic link. ->permission() already fails
58 	 * every walk of a component, but a jump lands on the root without
59 	 * one. Refuse here too so the root cannot be pinned by an O_PATH
60 	 * open or encoded into a file handle.
61 	 */
62 	return -EOPNOTSUPP;
63 }
64 
65 static char *failfs_dname(struct dentry *dentry, char *buffer, int buflen)
66 {
67 	return dynamic_dname(buffer, buflen, "failfs:/");
68 }
69 
70 static const struct dentry_operations failfs_dentry_operations = {
71 	.d_dname		= failfs_dname,
72 	.d_weak_revalidate	= failfs_d_weak_revalidate,
73 };
74 
75 static int failfs_statfs(struct dentry *dentry, struct kstatfs *buf)
76 {
77 	return -EOPNOTSUPP;
78 }
79 
80 static const struct super_operations failfs_super_operations = {
81 	.statfs	= failfs_statfs,
82 };
83 
84 static int failfs_fill_super(struct super_block *s, struct fs_context *fc)
85 {
86 	struct inode *inode;
87 
88 	s->s_maxbytes		= MAX_LFS_FILESIZE;
89 	s->s_blocksize		= PAGE_SIZE;
90 	s->s_blocksize_bits	= PAGE_SHIFT;
91 	s->s_magic		= FAIL_FS_MAGIC;
92 	s->s_op			= &failfs_super_operations;
93 	s->s_export_op		= NULL;
94 	s->s_xattr		= NULL;
95 	s->s_time_gran		= 1;
96 	s->s_d_flags		= 0;
97 
98 	inode = new_inode(s);
99 	if (!inode)
100 		return -ENOMEM;
101 
102 	/* failfs supports no operations... */
103 	inode->i_mode	= S_IFDIR;
104 	set_nlink(inode, 2);
105 	inode->i_op	= &failfs_dir_inode_operations;
106 	inode->i_fop	= &failfs_dir_operations;
107 	simple_inode_init_ts(inode);
108 	inode->i_ino	= 1;
109 	/* ... and is immutable. */
110 	inode->i_flags |= S_IMMUTABLE;
111 
112 	set_default_d_op(s, &failfs_dentry_operations);
113 	s->s_root = d_make_root(inode);
114 	if (!s->s_root)
115 		return -ENOMEM;
116 
117 	return 0;
118 }
119 
120 static int failfs_get_tree(struct fs_context *fc)
121 {
122 	return get_tree_single(fc, failfs_fill_super);
123 }
124 
125 static const struct fs_context_operations failfs_context_ops = {
126 	.get_tree	= failfs_get_tree,
127 };
128 
129 static int failfs_init_fs_context(struct fs_context *fc)
130 {
131 	fc->ops		= &failfs_context_ops;
132 	fc->global	= true;
133 	fc->sb_flags	|= SB_NOUSER;
134 	fc->s_iflags	|= SB_I_NOEXEC | SB_I_NODEV;
135 	return 0;
136 }
137 
138 static struct file_system_type failfs_fs_type = {
139 	.name			= "failfs",
140 	.init_fs_context	= failfs_init_fs_context,
141 	.kill_sb		= kill_anon_super,
142 };
143 
144 void __init failfs_init(void)
145 {
146 	struct vfsmount *mnt;
147 
148 	/* A single instance that is member of no mount namespace. */
149 	mnt = kern_mount(&failfs_fs_type);
150 	if (IS_ERR(mnt))
151 		panic("VFS: Failed to create failfs");
152 
153 	failfs_root_path.mnt	= mnt;
154 	failfs_root_path.dentry	= mnt->mnt_root;
155 }
156