~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/verity/measure.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Ioctl to get a verity file's digest
  4  *
  5  * Copyright 2019 Google LLC
  6  */
  7 
  8 #include "fsverity_private.h"
  9 
 10 #include <linux/bpf.h>
 11 #include <linux/btf.h>
 12 #include <linux/uaccess.h>
 13 
 14 /**
 15  * fsverity_ioctl_measure() - get a verity file's digest
 16  * @filp: file to get digest of
 17  * @_uarg: user pointer to fsverity_digest
 18  *
 19  * Retrieve the file digest that the kernel is enforcing for reads from a verity
 20  * file.  See the "FS_IOC_MEASURE_VERITY" section of
 21  * Documentation/filesystems/fsverity.rst for the documentation.
 22  *
 23  * Return: 0 on success, -errno on failure
 24  */
 25 int fsverity_ioctl_measure(struct file *filp, void __user *_uarg)
 26 {
 27         const struct inode *inode = file_inode(filp);
 28         struct fsverity_digest __user *uarg = _uarg;
 29         const struct fsverity_info *vi;
 30         const struct fsverity_hash_alg *hash_alg;
 31         struct fsverity_digest arg;
 32 
 33         vi = fsverity_get_info(inode);
 34         if (!vi)
 35                 return -ENODATA; /* not a verity file */
 36         hash_alg = vi->tree_params.hash_alg;
 37 
 38         /*
 39          * The user specifies the digest_size their buffer has space for; we can
 40          * return the digest if it fits in the available space.  We write back
 41          * the actual size, which may be shorter than the user-specified size.
 42          */
 43 
 44         if (get_user(arg.digest_size, &uarg->digest_size))
 45                 return -EFAULT;
 46         if (arg.digest_size < hash_alg->digest_size)
 47                 return -EOVERFLOW;
 48 
 49         memset(&arg, 0, sizeof(arg));
 50         arg.digest_algorithm = hash_alg - fsverity_hash_algs;
 51         arg.digest_size = hash_alg->digest_size;
 52 
 53         if (copy_to_user(uarg, &arg, sizeof(arg)))
 54                 return -EFAULT;
 55 
 56         if (copy_to_user(uarg->digest, vi->file_digest, hash_alg->digest_size))
 57                 return -EFAULT;
 58 
 59         return 0;
 60 }
 61 EXPORT_SYMBOL_GPL(fsverity_ioctl_measure);
 62 
 63 /**
 64  * fsverity_get_digest() - get a verity file's digest
 65  * @inode: inode to get digest of
 66  * @raw_digest: (out) the raw file digest
 67  * @alg: (out) the digest's algorithm, as a FS_VERITY_HASH_ALG_* value
 68  * @halg: (out) the digest's algorithm, as a HASH_ALGO_* value
 69  *
 70  * Retrieves the fsverity digest of the given file.  The file must have been
 71  * opened at least once since the inode was last loaded into the inode cache;
 72  * otherwise this function will not recognize when fsverity is enabled.
 73  *
 74  * The file's fsverity digest consists of @raw_digest in combination with either
 75  * @alg or @halg.  (The caller can choose which one of @alg or @halg to use.)
 76  *
 77  * IMPORTANT: Callers *must* make use of one of the two algorithm IDs, since
 78  * @raw_digest is meaningless without knowing which algorithm it uses!  fsverity
 79  * provides no security guarantee for users who ignore the algorithm ID, even if
 80  * they use the digest size (since algorithms can share the same digest size).
 81  *
 82  * Return: The size of the raw digest in bytes, or 0 if the file doesn't have
 83  *         fsverity enabled.
 84  */
 85 int fsverity_get_digest(struct inode *inode,
 86                         u8 raw_digest[FS_VERITY_MAX_DIGEST_SIZE],
 87                         u8 *alg, enum hash_algo *halg)
 88 {
 89         const struct fsverity_info *vi;
 90         const struct fsverity_hash_alg *hash_alg;
 91 
 92         vi = fsverity_get_info(inode);
 93         if (!vi)
 94                 return 0; /* not a verity file */
 95 
 96         hash_alg = vi->tree_params.hash_alg;
 97         memcpy(raw_digest, vi->file_digest, hash_alg->digest_size);
 98         if (alg)
 99                 *alg = hash_alg - fsverity_hash_algs;
100         if (halg)
101                 *halg = hash_alg->algo_id;
102         return hash_alg->digest_size;
103 }
104 EXPORT_SYMBOL_GPL(fsverity_get_digest);
105 
106 #ifdef CONFIG_BPF_SYSCALL
107 
108 /* bpf kfuncs */
109 __bpf_kfunc_start_defs();
110 
111 /**
112  * bpf_get_fsverity_digest: read fsverity digest of file
113  * @file: file to get digest from
114  * @digest_p: (out) dynptr for struct fsverity_digest
115  *
116  * Read fsverity_digest of *file* into *digest_ptr*.
117  *
118  * Return: 0 on success, a negative value on error.
119  */
120 __bpf_kfunc int bpf_get_fsverity_digest(struct file *file, struct bpf_dynptr *digest_p)
121 {
122         struct bpf_dynptr_kern *digest_ptr = (struct bpf_dynptr_kern *)digest_p;
123         const struct inode *inode = file_inode(file);
124         u32 dynptr_sz = __bpf_dynptr_size(digest_ptr);
125         struct fsverity_digest *arg;
126         const struct fsverity_info *vi;
127         const struct fsverity_hash_alg *hash_alg;
128         int out_digest_sz;
129 
130         if (dynptr_sz < sizeof(struct fsverity_digest))
131                 return -EINVAL;
132 
133         arg = __bpf_dynptr_data_rw(digest_ptr, dynptr_sz);
134         if (!arg)
135                 return -EINVAL;
136 
137         if (!IS_ALIGNED((uintptr_t)arg, __alignof__(*arg)))
138                 return -EINVAL;
139 
140         vi = fsverity_get_info(inode);
141         if (!vi)
142                 return -ENODATA; /* not a verity file */
143 
144         hash_alg = vi->tree_params.hash_alg;
145 
146         arg->digest_algorithm = hash_alg - fsverity_hash_algs;
147         arg->digest_size = hash_alg->digest_size;
148 
149         out_digest_sz = dynptr_sz - sizeof(struct fsverity_digest);
150 
151         /* copy digest */
152         memcpy(arg->digest, vi->file_digest,  min_t(int, hash_alg->digest_size, out_digest_sz));
153 
154         /* fill the extra buffer with zeros */
155         if (out_digest_sz > hash_alg->digest_size)
156                 memset(arg->digest + arg->digest_size, 0, out_digest_sz - hash_alg->digest_size);
157 
158         return 0;
159 }
160 
161 __bpf_kfunc_end_defs();
162 
163 BTF_KFUNCS_START(fsverity_set_ids)
164 BTF_ID_FLAGS(func, bpf_get_fsverity_digest, KF_TRUSTED_ARGS)
165 BTF_KFUNCS_END(fsverity_set_ids)
166 
167 static int bpf_get_fsverity_digest_filter(const struct bpf_prog *prog, u32 kfunc_id)
168 {
169         if (!btf_id_set8_contains(&fsverity_set_ids, kfunc_id))
170                 return 0;
171 
172         /* Only allow to attach from LSM hooks, to avoid recursion */
173         return prog->type != BPF_PROG_TYPE_LSM ? -EACCES : 0;
174 }
175 
176 static const struct btf_kfunc_id_set bpf_fsverity_set = {
177         .owner = THIS_MODULE,
178         .set = &fsverity_set_ids,
179         .filter = bpf_get_fsverity_digest_filter,
180 };
181 
182 void __init fsverity_init_bpf(void)
183 {
184         register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, &bpf_fsverity_set);
185 }
186 
187 #endif /* CONFIG_BPF_SYSCALL */
188 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php