Blame view

include/linux/fsverity.h 6.5 KB
fd2d1acfc   Eric Biggers   fs-verity: add th...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /* SPDX-License-Identifier: GPL-2.0 */
  /*
   * fs-verity: read-only file-based authenticity protection
   *
   * This header declares the interface between the fs/verity/ support layer and
   * filesystems that support fs-verity.
   *
   * Copyright 2019 Google LLC
   */
  
  #ifndef _LINUX_FSVERITY_H
  #define _LINUX_FSVERITY_H
  
  #include <linux/fs.h>
  #include <uapi/linux/fsverity.h>
  
  /* Verity operations for filesystems */
  struct fsverity_operations {
  
  	/**
3fda4c617   Eric Biggers   fs-verity: implem...
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  	 * Begin enabling verity on the given file.
  	 *
  	 * @filp: a readonly file descriptor for the file
  	 *
  	 * The filesystem must do any needed filesystem-specific preparations
  	 * for enabling verity, e.g. evicting inline data.  It also must return
  	 * -EBUSY if verity is already being enabled on the given file.
  	 *
  	 * i_rwsem is held for write.
  	 *
  	 * Return: 0 on success, -errno on failure
  	 */
  	int (*begin_enable_verity)(struct file *filp);
  
  	/**
  	 * End enabling verity on the given file.
  	 *
  	 * @filp: a readonly file descriptor for the file
  	 * @desc: the verity descriptor to write, or NULL on failure
  	 * @desc_size: size of verity descriptor, or 0 on failure
  	 * @merkle_tree_size: total bytes the Merkle tree took up
  	 *
  	 * If desc == NULL, then enabling verity failed and the filesystem only
  	 * must do any necessary cleanups.  Else, it must also store the given
  	 * verity descriptor to a fs-specific location associated with the inode
  	 * and do any fs-specific actions needed to mark the inode as a verity
  	 * inode, e.g. setting a bit in the on-disk inode.  The filesystem is
  	 * also responsible for setting the S_VERITY flag in the VFS inode.
  	 *
  	 * i_rwsem is held for write, but it may have been dropped between
  	 * ->begin_enable_verity() and ->end_enable_verity().
  	 *
  	 * Return: 0 on success, -errno on failure
  	 */
  	int (*end_enable_verity)(struct file *filp, const void *desc,
  				 size_t desc_size, u64 merkle_tree_size);
  
  	/**
fd2d1acfc   Eric Biggers   fs-verity: add th...
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  	 * Get the verity descriptor of the given inode.
  	 *
  	 * @inode: an inode with the S_VERITY flag set
  	 * @buf: buffer in which to place the verity descriptor
  	 * @bufsize: size of @buf, or 0 to retrieve the size only
  	 *
  	 * If bufsize == 0, then the size of the verity descriptor is returned.
  	 * Otherwise the verity descriptor is written to 'buf' and its actual
  	 * size is returned; -ERANGE is returned if it's too large.  This may be
  	 * called by multiple processes concurrently on the same inode.
  	 *
  	 * Return: the size on success, -errno on failure
  	 */
  	int (*get_verity_descriptor)(struct inode *inode, void *buf,
  				     size_t bufsize);
8a1d0f9ca   Eric Biggers   fs-verity: add da...
74
75
76
77
78
79
  
  	/**
  	 * Read a Merkle tree page of the given inode.
  	 *
  	 * @inode: the inode
  	 * @index: 0-based index of the page within the Merkle tree
fd39073db   Eric Biggers   fs-verity: implem...
80
81
82
83
  	 * @num_ra_pages: The number of Merkle tree pages that should be
  	 *		  prefetched starting at @index if the page at @index
  	 *		  isn't already cached.  Implementations may ignore this
  	 *		  argument; it's only a performance optimization.
8a1d0f9ca   Eric Biggers   fs-verity: add da...
84
85
86
87
88
89
90
91
92
93
  	 *
  	 * This can be called at any time on an open verity file, as well as
  	 * between ->begin_enable_verity() and ->end_enable_verity().  It may be
  	 * called by multiple processes concurrently, even with the same page.
  	 *
  	 * Note that this must retrieve a *page*, not necessarily a *block*.
  	 *
  	 * Return: the page on success, ERR_PTR() on failure
  	 */
  	struct page *(*read_merkle_tree_page)(struct inode *inode,
fd39073db   Eric Biggers   fs-verity: implem...
94
95
  					      pgoff_t index,
  					      unsigned long num_ra_pages);
3fda4c617   Eric Biggers   fs-verity: implem...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  
  	/**
  	 * Write a Merkle tree block to the given inode.
  	 *
  	 * @inode: the inode for which the Merkle tree is being built
  	 * @buf: block to write
  	 * @index: 0-based index of the block within the Merkle tree
  	 * @log_blocksize: log base 2 of the Merkle tree block size
  	 *
  	 * This is only called between ->begin_enable_verity() and
  	 * ->end_enable_verity().
  	 *
  	 * Return: 0 on success, -errno on failure
  	 */
  	int (*write_merkle_tree_block)(struct inode *inode, const void *buf,
  				       u64 index, int log_blocksize);
fd2d1acfc   Eric Biggers   fs-verity: add th...
112
113
114
115
116
117
  };
  
  #ifdef CONFIG_FS_VERITY
  
  static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
  {
f3db0bed4   Eric Biggers   fs-verity: use sm...
118
119
120
121
122
123
124
  	/*
  	 * Pairs with the cmpxchg_release() in fsverity_set_info().
  	 * I.e., another task may publish ->i_verity_info concurrently,
  	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
  	 * to safely ACQUIRE the memory the other task published.
  	 */
  	return smp_load_acquire(&inode->i_verity_info);
fd2d1acfc   Eric Biggers   fs-verity: add th...
125
  }
3fda4c617   Eric Biggers   fs-verity: implem...
126
  /* enable.c */
9cd6b593c   Eric Biggers   fs-verity: remove...
127
  int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
3fda4c617   Eric Biggers   fs-verity: implem...
128

4dd893d83   Eric Biggers   fs-verity: implem...
129
  /* measure.c */
9cd6b593c   Eric Biggers   fs-verity: remove...
130
  int fsverity_ioctl_measure(struct file *filp, void __user *arg);
4dd893d83   Eric Biggers   fs-verity: implem...
131

fd2d1acfc   Eric Biggers   fs-verity: add th...
132
  /* open.c */
9cd6b593c   Eric Biggers   fs-verity: remove...
133
134
135
  int fsverity_file_open(struct inode *inode, struct file *filp);
  int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr);
  void fsverity_cleanup_inode(struct inode *inode);
fd2d1acfc   Eric Biggers   fs-verity: add th...
136

8a1d0f9ca   Eric Biggers   fs-verity: add da...
137
  /* verify.c */
9cd6b593c   Eric Biggers   fs-verity: remove...
138
139
140
  bool fsverity_verify_page(struct page *page);
  void fsverity_verify_bio(struct bio *bio);
  void fsverity_enqueue_verify_work(struct work_struct *work);
8a1d0f9ca   Eric Biggers   fs-verity: add da...
141

fd2d1acfc   Eric Biggers   fs-verity: add th...
142
143
144
145
146
147
  #else /* !CONFIG_FS_VERITY */
  
  static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
  {
  	return NULL;
  }
3fda4c617   Eric Biggers   fs-verity: implem...
148
149
150
151
152
153
154
  /* enable.c */
  
  static inline int fsverity_ioctl_enable(struct file *filp,
  					const void __user *arg)
  {
  	return -EOPNOTSUPP;
  }
4dd893d83   Eric Biggers   fs-verity: implem...
155
156
157
158
159
160
  /* measure.c */
  
  static inline int fsverity_ioctl_measure(struct file *filp, void __user *arg)
  {
  	return -EOPNOTSUPP;
  }
fd2d1acfc   Eric Biggers   fs-verity: add th...
161
162
163
164
165
166
  /* open.c */
  
  static inline int fsverity_file_open(struct inode *inode, struct file *filp)
  {
  	return IS_VERITY(inode) ? -EOPNOTSUPP : 0;
  }
c1d9b584e   Eric Biggers   fs-verity: add th...
167
168
169
170
171
  static inline int fsverity_prepare_setattr(struct dentry *dentry,
  					   struct iattr *attr)
  {
  	return IS_VERITY(d_inode(dentry)) ? -EOPNOTSUPP : 0;
  }
fd2d1acfc   Eric Biggers   fs-verity: add th...
172
173
174
  static inline void fsverity_cleanup_inode(struct inode *inode)
  {
  }
8a1d0f9ca   Eric Biggers   fs-verity: add da...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  /* verify.c */
  
  static inline bool fsverity_verify_page(struct page *page)
  {
  	WARN_ON(1);
  	return false;
  }
  
  static inline void fsverity_verify_bio(struct bio *bio)
  {
  	WARN_ON(1);
  }
  
  static inline void fsverity_enqueue_verify_work(struct work_struct *work)
  {
  	WARN_ON(1);
  }
fd2d1acfc   Eric Biggers   fs-verity: add th...
192
  #endif	/* !CONFIG_FS_VERITY */
8a1d0f9ca   Eric Biggers   fs-verity: add da...
193
194
  /**
   * fsverity_active() - do reads from the inode need to go through fs-verity?
6377a38bd   Eric Biggers   fs-verity: fix al...
195
   * @inode: inode to check
8a1d0f9ca   Eric Biggers   fs-verity: add da...
196
197
198
199
200
201
202
   *
   * This checks whether ->i_verity_info has been set.
   *
   * Filesystems call this from ->readpages() to check whether the pages need to
   * be verified or not.  Don't use IS_VERITY() for this purpose; it's subject to
   * a race condition where the file is being read concurrently with
   * FS_IOC_ENABLE_VERITY completing.  (S_VERITY is set before ->i_verity_info.)
6377a38bd   Eric Biggers   fs-verity: fix al...
203
204
   *
   * Return: true if reads need to go through fs-verity, otherwise false
8a1d0f9ca   Eric Biggers   fs-verity: add da...
205
206
207
208
209
   */
  static inline bool fsverity_active(const struct inode *inode)
  {
  	return fsverity_get_info(inode) != NULL;
  }
fd2d1acfc   Eric Biggers   fs-verity: add th...
210
  #endif	/* _LINUX_FSVERITY_H */