1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 20b81d077SJaegeuk Kim /* 30b81d077SJaegeuk Kim * Encryption policy functions for per-file encryption support. 40b81d077SJaegeuk Kim * 50b81d077SJaegeuk Kim * Copyright (C) 2015, Google, Inc. 60b81d077SJaegeuk Kim * Copyright (C) 2015, Motorola Mobility. 70b81d077SJaegeuk Kim * 85dae460cSEric Biggers * Originally written by Michael Halcrow, 2015. 90b81d077SJaegeuk Kim * Modified by Jaegeuk Kim, 2015. 105dae460cSEric Biggers * Modified by Eric Biggers, 2019 for v2 policy support. 110b81d077SJaegeuk Kim */ 120b81d077SJaegeuk Kim 130b81d077SJaegeuk Kim #include <linux/random.h> 140b81d077SJaegeuk Kim #include <linux/string.h> 15ba63f23dSEric Biggers #include <linux/mount.h> 16cc4e0df0STheodore Ts'o #include "fscrypt_private.h" 170b81d077SJaegeuk Kim 185dae460cSEric Biggers /** 19d2fe9754SEric Biggers * fscrypt_policies_equal() - check whether two encryption policies are the same 20d2fe9754SEric Biggers * @policy1: the first policy 21d2fe9754SEric Biggers * @policy2: the second policy 225dae460cSEric Biggers * 235dae460cSEric Biggers * Return: %true if equal, else %false 240b81d077SJaegeuk Kim */ 255dae460cSEric Biggers bool fscrypt_policies_equal(const union fscrypt_policy *policy1, 265dae460cSEric Biggers const union fscrypt_policy *policy2) 270b81d077SJaegeuk Kim { 285dae460cSEric Biggers if (policy1->version != policy2->version) 295dae460cSEric Biggers return false; 305dae460cSEric Biggers 315dae460cSEric Biggers return !memcmp(policy1, policy2, fscrypt_policy_size(policy1)); 320b81d077SJaegeuk Kim } 330b81d077SJaegeuk Kim 34ef5b18b0SEric Biggers static bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode) 35ef5b18b0SEric Biggers { 36ef5b18b0SEric Biggers if (contents_mode == FSCRYPT_MODE_AES_256_XTS && 37ef5b18b0SEric Biggers filenames_mode == FSCRYPT_MODE_AES_256_CTS) 38ef5b18b0SEric Biggers return true; 39ef5b18b0SEric Biggers 40ef5b18b0SEric Biggers if (contents_mode == FSCRYPT_MODE_AES_128_CBC && 41ef5b18b0SEric Biggers filenames_mode == FSCRYPT_MODE_AES_128_CTS) 42ef5b18b0SEric Biggers return true; 43ef5b18b0SEric Biggers 44ef5b18b0SEric Biggers if (contents_mode == FSCRYPT_MODE_ADIANTUM && 45ef5b18b0SEric Biggers filenames_mode == FSCRYPT_MODE_ADIANTUM) 46ef5b18b0SEric Biggers return true; 47ef5b18b0SEric Biggers 48ef5b18b0SEric Biggers return false; 49ef5b18b0SEric Biggers } 50ef5b18b0SEric Biggers 5185af90e5SEric Biggers static bool supported_direct_key_modes(const struct inode *inode, 5285af90e5SEric Biggers u32 contents_mode, u32 filenames_mode) 5385af90e5SEric Biggers { 5485af90e5SEric Biggers const struct fscrypt_mode *mode; 5585af90e5SEric Biggers 5685af90e5SEric Biggers if (contents_mode != filenames_mode) { 5785af90e5SEric Biggers fscrypt_warn(inode, 5885af90e5SEric Biggers "Direct key flag not allowed with different contents and filenames modes"); 5985af90e5SEric Biggers return false; 6085af90e5SEric Biggers } 6185af90e5SEric Biggers mode = &fscrypt_modes[contents_mode]; 6285af90e5SEric Biggers 6385af90e5SEric Biggers if (mode->ivsize < offsetofend(union fscrypt_iv, nonce)) { 6485af90e5SEric Biggers fscrypt_warn(inode, "Direct key flag not allowed with %s", 6585af90e5SEric Biggers mode->friendly_name); 6685af90e5SEric Biggers return false; 6785af90e5SEric Biggers } 6885af90e5SEric Biggers return true; 6985af90e5SEric Biggers } 7085af90e5SEric Biggers 71b103fb76SEric Biggers static bool supported_iv_ino_lblk_64_policy( 72b103fb76SEric Biggers const struct fscrypt_policy_v2 *policy, 73b103fb76SEric Biggers const struct inode *inode) 74b103fb76SEric Biggers { 75b103fb76SEric Biggers struct super_block *sb = inode->i_sb; 76b103fb76SEric Biggers int ino_bits = 64, lblk_bits = 64; 77b103fb76SEric Biggers 78b103fb76SEric Biggers if (policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { 79b103fb76SEric Biggers fscrypt_warn(inode, 80b103fb76SEric Biggers "The DIRECT_KEY and IV_INO_LBLK_64 flags are mutually exclusive"); 81b103fb76SEric Biggers return false; 82b103fb76SEric Biggers } 83b103fb76SEric Biggers /* 84b103fb76SEric Biggers * It's unsafe to include inode numbers in the IVs if the filesystem can 85b103fb76SEric Biggers * potentially renumber inodes, e.g. via filesystem shrinking. 86b103fb76SEric Biggers */ 87b103fb76SEric Biggers if (!sb->s_cop->has_stable_inodes || 88b103fb76SEric Biggers !sb->s_cop->has_stable_inodes(sb)) { 89b103fb76SEric Biggers fscrypt_warn(inode, 90b103fb76SEric Biggers "Can't use IV_INO_LBLK_64 policy on filesystem '%s' because it doesn't have stable inode numbers", 91b103fb76SEric Biggers sb->s_id); 92b103fb76SEric Biggers return false; 93b103fb76SEric Biggers } 94b103fb76SEric Biggers if (sb->s_cop->get_ino_and_lblk_bits) 95b103fb76SEric Biggers sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits); 96b103fb76SEric Biggers if (ino_bits > 32 || lblk_bits > 32) { 97b103fb76SEric Biggers fscrypt_warn(inode, 98b103fb76SEric Biggers "Can't use IV_INO_LBLK_64 policy on filesystem '%s' because it doesn't use 32-bit inode and block numbers", 99b103fb76SEric Biggers sb->s_id); 100b103fb76SEric Biggers return false; 101b103fb76SEric Biggers } 102b103fb76SEric Biggers return true; 103b103fb76SEric Biggers } 104b103fb76SEric Biggers 105393a24a7SEric Biggers static bool fscrypt_supported_v1_policy(const struct fscrypt_policy_v1 *policy, 1065dae460cSEric Biggers const struct inode *inode) 1070b81d077SJaegeuk Kim { 108b7e7cf7aSDaniel Walter if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, 1095dae460cSEric Biggers policy->filenames_encryption_mode)) { 1105dae460cSEric Biggers fscrypt_warn(inode, 1115dae460cSEric Biggers "Unsupported encryption modes (contents %d, filenames %d)", 1125dae460cSEric Biggers policy->contents_encryption_mode, 1135dae460cSEric Biggers policy->filenames_encryption_mode); 1145dae460cSEric Biggers return false; 1155dae460cSEric Biggers } 1165dae460cSEric Biggers 117b103fb76SEric Biggers if (policy->flags & ~(FSCRYPT_POLICY_FLAGS_PAD_MASK | 118b103fb76SEric Biggers FSCRYPT_POLICY_FLAG_DIRECT_KEY)) { 119393a24a7SEric Biggers fscrypt_warn(inode, "Unsupported encryption flags (0x%02x)", 1205dae460cSEric Biggers policy->flags); 1215dae460cSEric Biggers return false; 1225dae460cSEric Biggers } 1235dae460cSEric Biggers 12485af90e5SEric Biggers if ((policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) && 12585af90e5SEric Biggers !supported_direct_key_modes(inode, policy->contents_encryption_mode, 12685af90e5SEric Biggers policy->filenames_encryption_mode)) 12785af90e5SEric Biggers return false; 12885af90e5SEric Biggers 1296e1918cfSDaniel Rosenberg if (IS_CASEFOLDED(inode)) { 1306e1918cfSDaniel Rosenberg /* With v1, there's no way to derive dirhash keys. */ 1316e1918cfSDaniel Rosenberg fscrypt_warn(inode, 1326e1918cfSDaniel Rosenberg "v1 policies can't be used on casefolded directories"); 1336e1918cfSDaniel Rosenberg return false; 1346e1918cfSDaniel Rosenberg } 1356e1918cfSDaniel Rosenberg 1365dae460cSEric Biggers return true; 1375dae460cSEric Biggers } 1385dae460cSEric Biggers 139393a24a7SEric Biggers static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy, 140393a24a7SEric Biggers const struct inode *inode) 141393a24a7SEric Biggers { 1425dae460cSEric Biggers if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, 1435dae460cSEric Biggers policy->filenames_encryption_mode)) { 1445dae460cSEric Biggers fscrypt_warn(inode, 1455dae460cSEric Biggers "Unsupported encryption modes (contents %d, filenames %d)", 1465dae460cSEric Biggers policy->contents_encryption_mode, 1475dae460cSEric Biggers policy->filenames_encryption_mode); 1485dae460cSEric Biggers return false; 1495dae460cSEric Biggers } 1505dae460cSEric Biggers 1515dae460cSEric Biggers if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) { 152393a24a7SEric Biggers fscrypt_warn(inode, "Unsupported encryption flags (0x%02x)", 1535dae460cSEric Biggers policy->flags); 1545dae460cSEric Biggers return false; 1555dae460cSEric Biggers } 1565dae460cSEric Biggers 15785af90e5SEric Biggers if ((policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) && 15885af90e5SEric Biggers !supported_direct_key_modes(inode, policy->contents_encryption_mode, 15985af90e5SEric Biggers policy->filenames_encryption_mode)) 16085af90e5SEric Biggers return false; 16185af90e5SEric Biggers 162b103fb76SEric Biggers if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) && 163b103fb76SEric Biggers !supported_iv_ino_lblk_64_policy(policy, inode)) 164b103fb76SEric Biggers return false; 165b103fb76SEric Biggers 166393a24a7SEric Biggers if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) { 167393a24a7SEric Biggers fscrypt_warn(inode, "Reserved bits set in encryption policy"); 1685dae460cSEric Biggers return false; 1695dae460cSEric Biggers } 1705dae460cSEric Biggers 1715dae460cSEric Biggers return true; 1725dae460cSEric Biggers } 173393a24a7SEric Biggers 174393a24a7SEric Biggers /** 175d2fe9754SEric Biggers * fscrypt_supported_policy() - check whether an encryption policy is supported 176d2fe9754SEric Biggers * @policy_u: the encryption policy 177d2fe9754SEric Biggers * @inode: the inode on which the policy will be used 178393a24a7SEric Biggers * 179393a24a7SEric Biggers * Given an encryption policy, check whether all its encryption modes and other 180393a24a7SEric Biggers * settings are supported by this kernel on the given inode. (But we don't 181393a24a7SEric Biggers * currently don't check for crypto API support here, so attempting to use an 182393a24a7SEric Biggers * algorithm not configured into the crypto API will still fail later.) 183393a24a7SEric Biggers * 184393a24a7SEric Biggers * Return: %true if supported, else %false 185393a24a7SEric Biggers */ 186393a24a7SEric Biggers bool fscrypt_supported_policy(const union fscrypt_policy *policy_u, 187393a24a7SEric Biggers const struct inode *inode) 188393a24a7SEric Biggers { 189393a24a7SEric Biggers switch (policy_u->version) { 190393a24a7SEric Biggers case FSCRYPT_POLICY_V1: 191393a24a7SEric Biggers return fscrypt_supported_v1_policy(&policy_u->v1, inode); 192393a24a7SEric Biggers case FSCRYPT_POLICY_V2: 193393a24a7SEric Biggers return fscrypt_supported_v2_policy(&policy_u->v2, inode); 1945dae460cSEric Biggers } 1955dae460cSEric Biggers return false; 1965dae460cSEric Biggers } 1975dae460cSEric Biggers 1985dae460cSEric Biggers /** 199d2fe9754SEric Biggers * fscrypt_new_context_from_policy() - create a new fscrypt_context from 200d2fe9754SEric Biggers * an fscrypt_policy 201d2fe9754SEric Biggers * @ctx_u: output context 202d2fe9754SEric Biggers * @policy_u: input policy 2035dae460cSEric Biggers * 2045dae460cSEric Biggers * Create an fscrypt_context for an inode that is being assigned the given 2055dae460cSEric Biggers * encryption policy. A new nonce is randomly generated. 2065dae460cSEric Biggers * 2075dae460cSEric Biggers * Return: the size of the new context in bytes. 2085dae460cSEric Biggers */ 2095dae460cSEric Biggers static int fscrypt_new_context_from_policy(union fscrypt_context *ctx_u, 2105dae460cSEric Biggers const union fscrypt_policy *policy_u) 2115dae460cSEric Biggers { 2125dae460cSEric Biggers memset(ctx_u, 0, sizeof(*ctx_u)); 2135dae460cSEric Biggers 2145dae460cSEric Biggers switch (policy_u->version) { 2155dae460cSEric Biggers case FSCRYPT_POLICY_V1: { 2165dae460cSEric Biggers const struct fscrypt_policy_v1 *policy = &policy_u->v1; 2175dae460cSEric Biggers struct fscrypt_context_v1 *ctx = &ctx_u->v1; 2185dae460cSEric Biggers 2195dae460cSEric Biggers ctx->version = FSCRYPT_CONTEXT_V1; 2205dae460cSEric Biggers ctx->contents_encryption_mode = 2215dae460cSEric Biggers policy->contents_encryption_mode; 2225dae460cSEric Biggers ctx->filenames_encryption_mode = 2235dae460cSEric Biggers policy->filenames_encryption_mode; 2245dae460cSEric Biggers ctx->flags = policy->flags; 2255dae460cSEric Biggers memcpy(ctx->master_key_descriptor, 2265dae460cSEric Biggers policy->master_key_descriptor, 2275dae460cSEric Biggers sizeof(ctx->master_key_descriptor)); 2285dae460cSEric Biggers get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); 2295dae460cSEric Biggers return sizeof(*ctx); 2305dae460cSEric Biggers } 2315dae460cSEric Biggers case FSCRYPT_POLICY_V2: { 2325dae460cSEric Biggers const struct fscrypt_policy_v2 *policy = &policy_u->v2; 2335dae460cSEric Biggers struct fscrypt_context_v2 *ctx = &ctx_u->v2; 2345dae460cSEric Biggers 2355dae460cSEric Biggers ctx->version = FSCRYPT_CONTEXT_V2; 2365dae460cSEric Biggers ctx->contents_encryption_mode = 2375dae460cSEric Biggers policy->contents_encryption_mode; 2385dae460cSEric Biggers ctx->filenames_encryption_mode = 2395dae460cSEric Biggers policy->filenames_encryption_mode; 2405dae460cSEric Biggers ctx->flags = policy->flags; 2415dae460cSEric Biggers memcpy(ctx->master_key_identifier, 2425dae460cSEric Biggers policy->master_key_identifier, 2435dae460cSEric Biggers sizeof(ctx->master_key_identifier)); 2445dae460cSEric Biggers get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); 2455dae460cSEric Biggers return sizeof(*ctx); 2465dae460cSEric Biggers } 2475dae460cSEric Biggers } 2485dae460cSEric Biggers BUG(); 2495dae460cSEric Biggers } 2505dae460cSEric Biggers 2515dae460cSEric Biggers /** 252d2fe9754SEric Biggers * fscrypt_policy_from_context() - convert an fscrypt_context to 253d2fe9754SEric Biggers * an fscrypt_policy 254d2fe9754SEric Biggers * @policy_u: output policy 255d2fe9754SEric Biggers * @ctx_u: input context 256d2fe9754SEric Biggers * @ctx_size: size of input context in bytes 2575dae460cSEric Biggers * 2585dae460cSEric Biggers * Given an fscrypt_context, build the corresponding fscrypt_policy. 2595dae460cSEric Biggers * 2605dae460cSEric Biggers * Return: 0 on success, or -EINVAL if the fscrypt_context has an unrecognized 2615dae460cSEric Biggers * version number or size. 2625dae460cSEric Biggers * 2635dae460cSEric Biggers * This does *not* validate the settings within the policy itself, e.g. the 2645dae460cSEric Biggers * modes, flags, and reserved bits. Use fscrypt_supported_policy() for that. 2655dae460cSEric Biggers */ 2665dae460cSEric Biggers int fscrypt_policy_from_context(union fscrypt_policy *policy_u, 2675dae460cSEric Biggers const union fscrypt_context *ctx_u, 2685dae460cSEric Biggers int ctx_size) 2695dae460cSEric Biggers { 2705dae460cSEric Biggers memset(policy_u, 0, sizeof(*policy_u)); 2715dae460cSEric Biggers 272e98ad464SEric Biggers if (!fscrypt_context_is_valid(ctx_u, ctx_size)) 2730b81d077SJaegeuk Kim return -EINVAL; 2740b81d077SJaegeuk Kim 2755dae460cSEric Biggers switch (ctx_u->version) { 2765dae460cSEric Biggers case FSCRYPT_CONTEXT_V1: { 2775dae460cSEric Biggers const struct fscrypt_context_v1 *ctx = &ctx_u->v1; 2785dae460cSEric Biggers struct fscrypt_policy_v1 *policy = &policy_u->v1; 2795dae460cSEric Biggers 2805dae460cSEric Biggers policy->version = FSCRYPT_POLICY_V1; 2815dae460cSEric Biggers policy->contents_encryption_mode = 2825dae460cSEric Biggers ctx->contents_encryption_mode; 2835dae460cSEric Biggers policy->filenames_encryption_mode = 2845dae460cSEric Biggers ctx->filenames_encryption_mode; 2855dae460cSEric Biggers policy->flags = ctx->flags; 2865dae460cSEric Biggers memcpy(policy->master_key_descriptor, 2875dae460cSEric Biggers ctx->master_key_descriptor, 2885dae460cSEric Biggers sizeof(policy->master_key_descriptor)); 2895dae460cSEric Biggers return 0; 2905dae460cSEric Biggers } 2915dae460cSEric Biggers case FSCRYPT_CONTEXT_V2: { 2925dae460cSEric Biggers const struct fscrypt_context_v2 *ctx = &ctx_u->v2; 2935dae460cSEric Biggers struct fscrypt_policy_v2 *policy = &policy_u->v2; 2945dae460cSEric Biggers 2955dae460cSEric Biggers policy->version = FSCRYPT_POLICY_V2; 2965dae460cSEric Biggers policy->contents_encryption_mode = 2975dae460cSEric Biggers ctx->contents_encryption_mode; 2985dae460cSEric Biggers policy->filenames_encryption_mode = 2995dae460cSEric Biggers ctx->filenames_encryption_mode; 3005dae460cSEric Biggers policy->flags = ctx->flags; 3015dae460cSEric Biggers memcpy(policy->__reserved, ctx->__reserved, 3025dae460cSEric Biggers sizeof(policy->__reserved)); 3035dae460cSEric Biggers memcpy(policy->master_key_identifier, 3045dae460cSEric Biggers ctx->master_key_identifier, 3055dae460cSEric Biggers sizeof(policy->master_key_identifier)); 3065dae460cSEric Biggers return 0; 3075dae460cSEric Biggers } 3085dae460cSEric Biggers } 3095dae460cSEric Biggers /* unreachable */ 3105dae460cSEric Biggers return -EINVAL; 3115dae460cSEric Biggers } 3125dae460cSEric Biggers 3135dae460cSEric Biggers /* Retrieve an inode's encryption policy */ 3145dae460cSEric Biggers static int fscrypt_get_policy(struct inode *inode, union fscrypt_policy *policy) 3155dae460cSEric Biggers { 3165dae460cSEric Biggers const struct fscrypt_info *ci; 3175dae460cSEric Biggers union fscrypt_context ctx; 3185dae460cSEric Biggers int ret; 3195dae460cSEric Biggers 3205dae460cSEric Biggers ci = READ_ONCE(inode->i_crypt_info); 3215dae460cSEric Biggers if (ci) { 3225dae460cSEric Biggers /* key available, use the cached policy */ 3235dae460cSEric Biggers *policy = ci->ci_policy; 3245dae460cSEric Biggers return 0; 3255dae460cSEric Biggers } 3265dae460cSEric Biggers 3275dae460cSEric Biggers if (!IS_ENCRYPTED(inode)) 3285dae460cSEric Biggers return -ENODATA; 3295dae460cSEric Biggers 3305dae460cSEric Biggers ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); 3315dae460cSEric Biggers if (ret < 0) 3325dae460cSEric Biggers return (ret == -ERANGE) ? -EINVAL : ret; 3335dae460cSEric Biggers 3345dae460cSEric Biggers return fscrypt_policy_from_context(policy, &ctx, ret); 3355dae460cSEric Biggers } 3365dae460cSEric Biggers 3375dae460cSEric Biggers static int set_encryption_policy(struct inode *inode, 3385dae460cSEric Biggers const union fscrypt_policy *policy) 3395dae460cSEric Biggers { 3405dae460cSEric Biggers union fscrypt_context ctx; 3415dae460cSEric Biggers int ctxsize; 3425ab7189aSEric Biggers int err; 3435dae460cSEric Biggers 3445dae460cSEric Biggers if (!fscrypt_supported_policy(policy, inode)) 3450b81d077SJaegeuk Kim return -EINVAL; 3460b81d077SJaegeuk Kim 3475ab7189aSEric Biggers switch (policy->version) { 3485ab7189aSEric Biggers case FSCRYPT_POLICY_V1: 3495dae460cSEric Biggers /* 3505dae460cSEric Biggers * The original encryption policy version provided no way of 3515dae460cSEric Biggers * verifying that the correct master key was supplied, which was 3525dae460cSEric Biggers * insecure in scenarios where multiple users have access to the 3535dae460cSEric Biggers * same encrypted files (even just read-only access). The new 3545dae460cSEric Biggers * encryption policy version fixes this and also implies use of 3555dae460cSEric Biggers * an improved key derivation function and allows non-root users 3565dae460cSEric Biggers * to securely remove keys. So as long as compatibility with 3575dae460cSEric Biggers * old kernels isn't required, it is recommended to use the new 3585dae460cSEric Biggers * policy version for all new encrypted directories. 3595dae460cSEric Biggers */ 3605dae460cSEric Biggers pr_warn_once("%s (pid %d) is setting deprecated v1 encryption policy; recommend upgrading to v2.\n", 3615dae460cSEric Biggers current->comm, current->pid); 3625ab7189aSEric Biggers break; 3635ab7189aSEric Biggers case FSCRYPT_POLICY_V2: 3645ab7189aSEric Biggers err = fscrypt_verify_key_added(inode->i_sb, 3655ab7189aSEric Biggers policy->v2.master_key_identifier); 3665ab7189aSEric Biggers if (err) 3675ab7189aSEric Biggers return err; 3685ab7189aSEric Biggers break; 3695ab7189aSEric Biggers default: 3705ab7189aSEric Biggers WARN_ON(1); 3715ab7189aSEric Biggers return -EINVAL; 3725dae460cSEric Biggers } 3730b81d077SJaegeuk Kim 3745dae460cSEric Biggers ctxsize = fscrypt_new_context_from_policy(&ctx, policy); 3755dae460cSEric Biggers 3765dae460cSEric Biggers return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, NULL); 3770b81d077SJaegeuk Kim } 3780b81d077SJaegeuk Kim 379db717d8eSEric Biggers int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) 3800b81d077SJaegeuk Kim { 3815dae460cSEric Biggers union fscrypt_policy policy; 3825dae460cSEric Biggers union fscrypt_policy existing_policy; 383ba63f23dSEric Biggers struct inode *inode = file_inode(filp); 3845dae460cSEric Biggers u8 version; 3855dae460cSEric Biggers int size; 386ba63f23dSEric Biggers int ret; 387ba63f23dSEric Biggers 3885dae460cSEric Biggers if (get_user(policy.version, (const u8 __user *)arg)) 389db717d8eSEric Biggers return -EFAULT; 390db717d8eSEric Biggers 3915dae460cSEric Biggers size = fscrypt_policy_size(&policy); 3925dae460cSEric Biggers if (size <= 0) 3935dae460cSEric Biggers return -EINVAL; 3945dae460cSEric Biggers 3955dae460cSEric Biggers /* 3965dae460cSEric Biggers * We should just copy the remaining 'size - 1' bytes here, but a 3975dae460cSEric Biggers * bizarre bug in gcc 7 and earlier (fixed by gcc r255731) causes gcc to 3985dae460cSEric Biggers * think that size can be 0 here (despite the check above!) *and* that 3995dae460cSEric Biggers * it's a compile-time constant. Thus it would think copy_from_user() 4005dae460cSEric Biggers * is passed compile-time constant ULONG_MAX, causing the compile-time 4015dae460cSEric Biggers * buffer overflow check to fail, breaking the build. This only occurred 4025dae460cSEric Biggers * when building an i386 kernel with -Os and branch profiling enabled. 4035dae460cSEric Biggers * 4045dae460cSEric Biggers * Work around it by just copying the first byte again... 4055dae460cSEric Biggers */ 4065dae460cSEric Biggers version = policy.version; 4075dae460cSEric Biggers if (copy_from_user(&policy, arg, size)) 4085dae460cSEric Biggers return -EFAULT; 4095dae460cSEric Biggers policy.version = version; 4105dae460cSEric Biggers 411163ae1c6SEric Biggers if (!inode_owner_or_capable(inode)) 412163ae1c6SEric Biggers return -EACCES; 413163ae1c6SEric Biggers 414ba63f23dSEric Biggers ret = mnt_want_write_file(filp); 415ba63f23dSEric Biggers if (ret) 416ba63f23dSEric Biggers return ret; 417ba63f23dSEric Biggers 4188906a822SEric Biggers inode_lock(inode); 4198906a822SEric Biggers 4205dae460cSEric Biggers ret = fscrypt_get_policy(inode, &existing_policy); 421efee590eSEric Biggers if (ret == -ENODATA) { 422002ced4bSEric Biggers if (!S_ISDIR(inode->i_mode)) 423dffd0cfaSEric Biggers ret = -ENOTDIR; 4245858bdadSHongjie Fang else if (IS_DEADDIR(inode)) 4255858bdadSHongjie Fang ret = -ENOENT; 426ba63f23dSEric Biggers else if (!inode->i_sb->s_cop->empty_dir(inode)) 427ba63f23dSEric Biggers ret = -ENOTEMPTY; 428ba63f23dSEric Biggers else 4295dae460cSEric Biggers ret = set_encryption_policy(inode, &policy); 4305dae460cSEric Biggers } else if (ret == -EINVAL || 4315dae460cSEric Biggers (ret == 0 && !fscrypt_policies_equal(&policy, 4325dae460cSEric Biggers &existing_policy))) { 433efee590eSEric Biggers /* The file already uses a different encryption policy. */ 4348488cd96SEric Biggers ret = -EEXIST; 4350b81d077SJaegeuk Kim } 4360b81d077SJaegeuk Kim 4378906a822SEric Biggers inode_unlock(inode); 4388906a822SEric Biggers 439ba63f23dSEric Biggers mnt_drop_write_file(filp); 440ba63f23dSEric Biggers return ret; 4410b81d077SJaegeuk Kim } 442db717d8eSEric Biggers EXPORT_SYMBOL(fscrypt_ioctl_set_policy); 4430b81d077SJaegeuk Kim 4445dae460cSEric Biggers /* Original ioctl version; can only get the original policy version */ 445db717d8eSEric Biggers int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) 4460b81d077SJaegeuk Kim { 4475dae460cSEric Biggers union fscrypt_policy policy; 4485dae460cSEric Biggers int err; 4490b81d077SJaegeuk Kim 4505dae460cSEric Biggers err = fscrypt_get_policy(file_inode(filp), &policy); 4515dae460cSEric Biggers if (err) 4525dae460cSEric Biggers return err; 4530b81d077SJaegeuk Kim 4545dae460cSEric Biggers if (policy.version != FSCRYPT_POLICY_V1) 4550b81d077SJaegeuk Kim return -EINVAL; 4560b81d077SJaegeuk Kim 4575dae460cSEric Biggers if (copy_to_user(arg, &policy, sizeof(policy.v1))) 458db717d8eSEric Biggers return -EFAULT; 4590b81d077SJaegeuk Kim return 0; 4600b81d077SJaegeuk Kim } 461db717d8eSEric Biggers EXPORT_SYMBOL(fscrypt_ioctl_get_policy); 4620b81d077SJaegeuk Kim 4635dae460cSEric Biggers /* Extended ioctl version; can get policies of any version */ 4645dae460cSEric Biggers int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg) 4655dae460cSEric Biggers { 4665dae460cSEric Biggers struct fscrypt_get_policy_ex_arg arg; 4675dae460cSEric Biggers union fscrypt_policy *policy = (union fscrypt_policy *)&arg.policy; 4685dae460cSEric Biggers size_t policy_size; 4695dae460cSEric Biggers int err; 4705dae460cSEric Biggers 4715dae460cSEric Biggers /* arg is policy_size, then policy */ 4725dae460cSEric Biggers BUILD_BUG_ON(offsetof(typeof(arg), policy_size) != 0); 4735dae460cSEric Biggers BUILD_BUG_ON(offsetofend(typeof(arg), policy_size) != 4745dae460cSEric Biggers offsetof(typeof(arg), policy)); 4755dae460cSEric Biggers BUILD_BUG_ON(sizeof(arg.policy) != sizeof(*policy)); 4765dae460cSEric Biggers 4775dae460cSEric Biggers err = fscrypt_get_policy(file_inode(filp), policy); 4785dae460cSEric Biggers if (err) 4795dae460cSEric Biggers return err; 4805dae460cSEric Biggers policy_size = fscrypt_policy_size(policy); 4815dae460cSEric Biggers 4825dae460cSEric Biggers if (copy_from_user(&arg, uarg, sizeof(arg.policy_size))) 4835dae460cSEric Biggers return -EFAULT; 4845dae460cSEric Biggers 4855dae460cSEric Biggers if (policy_size > arg.policy_size) 4865dae460cSEric Biggers return -EOVERFLOW; 4875dae460cSEric Biggers arg.policy_size = policy_size; 4885dae460cSEric Biggers 4895dae460cSEric Biggers if (copy_to_user(uarg, &arg, sizeof(arg.policy_size) + policy_size)) 4905dae460cSEric Biggers return -EFAULT; 4915dae460cSEric Biggers return 0; 4925dae460cSEric Biggers } 4935dae460cSEric Biggers EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex); 4945dae460cSEric Biggers 495e98ad464SEric Biggers /* FS_IOC_GET_ENCRYPTION_NONCE: retrieve file's encryption nonce for testing */ 496e98ad464SEric Biggers int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg) 497e98ad464SEric Biggers { 498e98ad464SEric Biggers struct inode *inode = file_inode(filp); 499e98ad464SEric Biggers union fscrypt_context ctx; 500e98ad464SEric Biggers int ret; 501e98ad464SEric Biggers 502e98ad464SEric Biggers ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); 503e98ad464SEric Biggers if (ret < 0) 504e98ad464SEric Biggers return ret; 505e98ad464SEric Biggers if (!fscrypt_context_is_valid(&ctx, ret)) 506e98ad464SEric Biggers return -EINVAL; 507e98ad464SEric Biggers if (copy_to_user(arg, fscrypt_context_nonce(&ctx), 508e98ad464SEric Biggers FS_KEY_DERIVATION_NONCE_SIZE)) 509e98ad464SEric Biggers return -EFAULT; 510e98ad464SEric Biggers return 0; 511e98ad464SEric Biggers } 512e98ad464SEric Biggers EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_nonce); 513e98ad464SEric Biggers 514272f98f6SEric Biggers /** 515272f98f6SEric Biggers * fscrypt_has_permitted_context() - is a file's encryption policy permitted 516272f98f6SEric Biggers * within its directory? 517272f98f6SEric Biggers * 518272f98f6SEric Biggers * @parent: inode for parent directory 519272f98f6SEric Biggers * @child: inode for file being looked up, opened, or linked into @parent 520272f98f6SEric Biggers * 521272f98f6SEric Biggers * Filesystems must call this before permitting access to an inode in a 522272f98f6SEric Biggers * situation where the parent directory is encrypted (either before allowing 523272f98f6SEric Biggers * ->lookup() to succeed, or for a regular file before allowing it to be opened) 524272f98f6SEric Biggers * and before any operation that involves linking an inode into an encrypted 525272f98f6SEric Biggers * directory, including link, rename, and cross rename. It enforces the 526272f98f6SEric Biggers * constraint that within a given encrypted directory tree, all files use the 527272f98f6SEric Biggers * same encryption policy. The pre-access check is needed to detect potentially 528272f98f6SEric Biggers * malicious offline violations of this constraint, while the link and rename 529272f98f6SEric Biggers * checks are needed to prevent online violations of this constraint. 530272f98f6SEric Biggers * 531f5e55e77SEric Biggers * Return: 1 if permitted, 0 if forbidden. 532272f98f6SEric Biggers */ 5330b81d077SJaegeuk Kim int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) 5340b81d077SJaegeuk Kim { 5355dae460cSEric Biggers union fscrypt_policy parent_policy, child_policy; 5365dae460cSEric Biggers int err; 5370b81d077SJaegeuk Kim 53842d97eb0SEric Biggers /* No restrictions on file types which are never encrypted */ 53942d97eb0SEric Biggers if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) && 54042d97eb0SEric Biggers !S_ISLNK(child->i_mode)) 54142d97eb0SEric Biggers return 1; 54242d97eb0SEric Biggers 543272f98f6SEric Biggers /* No restrictions if the parent directory is unencrypted */ 544e0428a26SEric Biggers if (!IS_ENCRYPTED(parent)) 5450b81d077SJaegeuk Kim return 1; 546272f98f6SEric Biggers 547272f98f6SEric Biggers /* Encrypted directories must not contain unencrypted files */ 548e0428a26SEric Biggers if (!IS_ENCRYPTED(child)) 5490b81d077SJaegeuk Kim return 0; 550272f98f6SEric Biggers 551272f98f6SEric Biggers /* 552272f98f6SEric Biggers * Both parent and child are encrypted, so verify they use the same 553272f98f6SEric Biggers * encryption policy. Compare the fscrypt_info structs if the keys are 554272f98f6SEric Biggers * available, otherwise retrieve and compare the fscrypt_contexts. 555272f98f6SEric Biggers * 556272f98f6SEric Biggers * Note that the fscrypt_context retrieval will be required frequently 557272f98f6SEric Biggers * when accessing an encrypted directory tree without the key. 558272f98f6SEric Biggers * Performance-wise this is not a big deal because we already don't 559272f98f6SEric Biggers * really optimize for file access without the key (to the extent that 560272f98f6SEric Biggers * such access is even possible), given that any attempted access 561272f98f6SEric Biggers * already causes a fscrypt_context retrieval and keyring search. 562272f98f6SEric Biggers * 563272f98f6SEric Biggers * In any case, if an unexpected error occurs, fall back to "forbidden". 564272f98f6SEric Biggers */ 565272f98f6SEric Biggers 5665dae460cSEric Biggers err = fscrypt_get_encryption_info(parent); 5675dae460cSEric Biggers if (err) 5680b81d077SJaegeuk Kim return 0; 5695dae460cSEric Biggers err = fscrypt_get_encryption_info(child); 5705dae460cSEric Biggers if (err) 571272f98f6SEric Biggers return 0; 572272f98f6SEric Biggers 5735dae460cSEric Biggers err = fscrypt_get_policy(parent, &parent_policy); 5745dae460cSEric Biggers if (err) 575272f98f6SEric Biggers return 0; 576272f98f6SEric Biggers 5775dae460cSEric Biggers err = fscrypt_get_policy(child, &child_policy); 5785dae460cSEric Biggers if (err) 5795dae460cSEric Biggers return 0; 5805dae460cSEric Biggers 5815dae460cSEric Biggers return fscrypt_policies_equal(&parent_policy, &child_policy); 5820b81d077SJaegeuk Kim } 5830b81d077SJaegeuk Kim EXPORT_SYMBOL(fscrypt_has_permitted_context); 5840b81d077SJaegeuk Kim 5850b81d077SJaegeuk Kim /** 5860b81d077SJaegeuk Kim * fscrypt_inherit_context() - Sets a child context from its parent 5870b81d077SJaegeuk Kim * @parent: Parent inode from which the context is inherited. 5880b81d077SJaegeuk Kim * @child: Child inode that inherits the context from @parent. 5890b81d077SJaegeuk Kim * @fs_data: private data given by FS. 5905bbdcbbbSTheodore Ts'o * @preload: preload child i_crypt_info if true 5910b81d077SJaegeuk Kim * 5925bbdcbbbSTheodore Ts'o * Return: 0 on success, -errno on failure 5930b81d077SJaegeuk Kim */ 5940b81d077SJaegeuk Kim int fscrypt_inherit_context(struct inode *parent, struct inode *child, 5950b81d077SJaegeuk Kim void *fs_data, bool preload) 5960b81d077SJaegeuk Kim { 5975dae460cSEric Biggers union fscrypt_context ctx; 5985dae460cSEric Biggers int ctxsize; 5990b81d077SJaegeuk Kim struct fscrypt_info *ci; 6000b81d077SJaegeuk Kim int res; 6010b81d077SJaegeuk Kim 6020b81d077SJaegeuk Kim res = fscrypt_get_encryption_info(parent); 6030b81d077SJaegeuk Kim if (res < 0) 6040b81d077SJaegeuk Kim return res; 6050b81d077SJaegeuk Kim 606e37a784dSEric Biggers ci = READ_ONCE(parent->i_crypt_info); 6070b81d077SJaegeuk Kim if (ci == NULL) 6080b81d077SJaegeuk Kim return -ENOKEY; 6090b81d077SJaegeuk Kim 6105dae460cSEric Biggers ctxsize = fscrypt_new_context_from_policy(&ctx, &ci->ci_policy); 6115dae460cSEric Biggers 612af65207cSTahsin Erdogan BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); 6135dae460cSEric Biggers res = parent->i_sb->s_cop->set_context(child, &ctx, ctxsize, fs_data); 6140b81d077SJaegeuk Kim if (res) 6150b81d077SJaegeuk Kim return res; 6160b81d077SJaegeuk Kim return preload ? fscrypt_get_encryption_info(child): 0; 6170b81d077SJaegeuk Kim } 6180b81d077SJaegeuk Kim EXPORT_SYMBOL(fscrypt_inherit_context); 619