policy.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Encryption policy functions for per-file encryption support.
  3. *
  4. * Copyright (C) 2015, Google, Inc.
  5. * Copyright (C) 2015, Motorola Mobility.
  6. *
  7. * Written by Michael Halcrow, 2015.
  8. * Modified by Jaegeuk Kim, 2015.
  9. */
  10. #include <linux/random.h>
  11. #include <linux/string.h>
  12. #include <linux/mount.h>
  13. #include "fscrypt_private.h"
  14. /*
  15. * check whether an encryption policy is consistent with an encryption context
  16. */
  17. static bool is_encryption_context_consistent_with_policy(
  18. const struct fscrypt_context *ctx,
  19. const struct fscrypt_policy *policy)
  20. {
  21. return memcmp(ctx->master_key_descriptor, policy->master_key_descriptor,
  22. FS_KEY_DESCRIPTOR_SIZE) == 0 &&
  23. (ctx->flags == policy->flags) &&
  24. (ctx->contents_encryption_mode ==
  25. policy->contents_encryption_mode) &&
  26. (ctx->filenames_encryption_mode ==
  27. policy->filenames_encryption_mode);
  28. }
  29. static int create_encryption_context_from_policy(struct inode *inode,
  30. const struct fscrypt_policy *policy)
  31. {
  32. struct fscrypt_context ctx;
  33. ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
  34. memcpy(ctx.master_key_descriptor, policy->master_key_descriptor,
  35. FS_KEY_DESCRIPTOR_SIZE);
  36. if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode,
  37. policy->filenames_encryption_mode))
  38. return -EINVAL;
  39. if (policy->flags & ~FS_POLICY_FLAGS_VALID)
  40. return -EINVAL;
  41. ctx.contents_encryption_mode = policy->contents_encryption_mode;
  42. ctx.filenames_encryption_mode = policy->filenames_encryption_mode;
  43. ctx.flags = policy->flags;
  44. BUILD_BUG_ON(sizeof(ctx.nonce) != FS_KEY_DERIVATION_NONCE_SIZE);
  45. get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE);
  46. return inode->i_sb->s_cop->set_context(inode, &ctx, sizeof(ctx), NULL);
  47. }
  48. int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
  49. {
  50. struct fscrypt_policy policy;
  51. struct inode *inode = file_inode(filp);
  52. int ret;
  53. struct fscrypt_context ctx;
  54. if (copy_from_user(&policy, arg, sizeof(policy)))
  55. return -EFAULT;
  56. if (!inode_owner_or_capable(inode))
  57. return -EACCES;
  58. if (policy.version != 0)
  59. return -EINVAL;
  60. ret = mnt_want_write_file(filp);
  61. if (ret)
  62. return ret;
  63. inode_lock(inode);
  64. ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
  65. if (ret == -ENODATA) {
  66. if (!S_ISDIR(inode->i_mode))
  67. ret = -ENOTDIR;
  68. else if (!inode->i_sb->s_cop->empty_dir(inode))
  69. ret = -ENOTEMPTY;
  70. else
  71. ret = create_encryption_context_from_policy(inode,
  72. &policy);
  73. } else if (ret == sizeof(ctx) &&
  74. is_encryption_context_consistent_with_policy(&ctx,
  75. &policy)) {
  76. /* The file already uses the same encryption policy. */
  77. ret = 0;
  78. } else if (ret >= 0 || ret == -ERANGE) {
  79. /* The file already uses a different encryption policy. */
  80. ret = -EEXIST;
  81. }
  82. inode_unlock(inode);
  83. mnt_drop_write_file(filp);
  84. return ret;
  85. }
  86. EXPORT_SYMBOL(fscrypt_ioctl_set_policy);
  87. int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
  88. {
  89. struct inode *inode = file_inode(filp);
  90. struct fscrypt_context ctx;
  91. struct fscrypt_policy policy;
  92. int res;
  93. if (!inode->i_sb->s_cop->is_encrypted(inode))
  94. return -ENODATA;
  95. res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
  96. if (res < 0 && res != -ERANGE)
  97. return res;
  98. if (res != sizeof(ctx))
  99. return -EINVAL;
  100. if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1)
  101. return -EINVAL;
  102. policy.version = 0;
  103. policy.contents_encryption_mode = ctx.contents_encryption_mode;
  104. policy.filenames_encryption_mode = ctx.filenames_encryption_mode;
  105. policy.flags = ctx.flags;
  106. memcpy(policy.master_key_descriptor, ctx.master_key_descriptor,
  107. FS_KEY_DESCRIPTOR_SIZE);
  108. if (copy_to_user(arg, &policy, sizeof(policy)))
  109. return -EFAULT;
  110. return 0;
  111. }
  112. EXPORT_SYMBOL(fscrypt_ioctl_get_policy);
  113. /**
  114. * fscrypt_has_permitted_context() - is a file's encryption policy permitted
  115. * within its directory?
  116. *
  117. * @parent: inode for parent directory
  118. * @child: inode for file being looked up, opened, or linked into @parent
  119. *
  120. * Filesystems must call this before permitting access to an inode in a
  121. * situation where the parent directory is encrypted (either before allowing
  122. * ->lookup() to succeed, or for a regular file before allowing it to be opened)
  123. * and before any operation that involves linking an inode into an encrypted
  124. * directory, including link, rename, and cross rename. It enforces the
  125. * constraint that within a given encrypted directory tree, all files use the
  126. * same encryption policy. The pre-access check is needed to detect potentially
  127. * malicious offline violations of this constraint, while the link and rename
  128. * checks are needed to prevent online violations of this constraint.
  129. *
  130. * Return: 1 if permitted, 0 if forbidden. If forbidden, the caller must fail
  131. * the filesystem operation with EPERM.
  132. */
  133. int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
  134. {
  135. const struct fscrypt_operations *cops = parent->i_sb->s_cop;
  136. const struct fscrypt_info *parent_ci, *child_ci;
  137. struct fscrypt_context parent_ctx, child_ctx;
  138. int res;
  139. /* No restrictions on file types which are never encrypted */
  140. if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) &&
  141. !S_ISLNK(child->i_mode))
  142. return 1;
  143. /* No restrictions if the parent directory is unencrypted */
  144. if (!cops->is_encrypted(parent))
  145. return 1;
  146. /* Encrypted directories must not contain unencrypted files */
  147. if (!cops->is_encrypted(child))
  148. return 0;
  149. /*
  150. * Both parent and child are encrypted, so verify they use the same
  151. * encryption policy. Compare the fscrypt_info structs if the keys are
  152. * available, otherwise retrieve and compare the fscrypt_contexts.
  153. *
  154. * Note that the fscrypt_context retrieval will be required frequently
  155. * when accessing an encrypted directory tree without the key.
  156. * Performance-wise this is not a big deal because we already don't
  157. * really optimize for file access without the key (to the extent that
  158. * such access is even possible), given that any attempted access
  159. * already causes a fscrypt_context retrieval and keyring search.
  160. *
  161. * In any case, if an unexpected error occurs, fall back to "forbidden".
  162. */
  163. res = fscrypt_get_encryption_info(parent);
  164. if (res)
  165. return 0;
  166. res = fscrypt_get_encryption_info(child);
  167. if (res)
  168. return 0;
  169. parent_ci = parent->i_crypt_info;
  170. child_ci = child->i_crypt_info;
  171. if (parent_ci && child_ci) {
  172. return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key,
  173. FS_KEY_DESCRIPTOR_SIZE) == 0 &&
  174. (parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
  175. (parent_ci->ci_filename_mode ==
  176. child_ci->ci_filename_mode) &&
  177. (parent_ci->ci_flags == child_ci->ci_flags);
  178. }
  179. res = cops->get_context(parent, &parent_ctx, sizeof(parent_ctx));
  180. if (res != sizeof(parent_ctx))
  181. return 0;
  182. res = cops->get_context(child, &child_ctx, sizeof(child_ctx));
  183. if (res != sizeof(child_ctx))
  184. return 0;
  185. return memcmp(parent_ctx.master_key_descriptor,
  186. child_ctx.master_key_descriptor,
  187. FS_KEY_DESCRIPTOR_SIZE) == 0 &&
  188. (parent_ctx.contents_encryption_mode ==
  189. child_ctx.contents_encryption_mode) &&
  190. (parent_ctx.filenames_encryption_mode ==
  191. child_ctx.filenames_encryption_mode) &&
  192. (parent_ctx.flags == child_ctx.flags);
  193. }
  194. EXPORT_SYMBOL(fscrypt_has_permitted_context);
  195. /**
  196. * fscrypt_inherit_context() - Sets a child context from its parent
  197. * @parent: Parent inode from which the context is inherited.
  198. * @child: Child inode that inherits the context from @parent.
  199. * @fs_data: private data given by FS.
  200. * @preload: preload child i_crypt_info if true
  201. *
  202. * Return: 0 on success, -errno on failure
  203. */
  204. int fscrypt_inherit_context(struct inode *parent, struct inode *child,
  205. void *fs_data, bool preload)
  206. {
  207. struct fscrypt_context ctx;
  208. struct fscrypt_info *ci;
  209. int res;
  210. res = fscrypt_get_encryption_info(parent);
  211. if (res < 0)
  212. return res;
  213. ci = parent->i_crypt_info;
  214. if (ci == NULL)
  215. return -ENOKEY;
  216. ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
  217. ctx.contents_encryption_mode = ci->ci_data_mode;
  218. ctx.filenames_encryption_mode = ci->ci_filename_mode;
  219. ctx.flags = ci->ci_flags;
  220. memcpy(ctx.master_key_descriptor, ci->ci_master_key,
  221. FS_KEY_DESCRIPTOR_SIZE);
  222. get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE);
  223. BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE);
  224. res = parent->i_sb->s_cop->set_context(child, &ctx,
  225. sizeof(ctx), fs_data);
  226. if (res)
  227. return res;
  228. return preload ? fscrypt_get_encryption_info(child): 0;
  229. }
  230. EXPORT_SYMBOL(fscrypt_inherit_context);