Whamcloud - gitweb
LU-12275 sec: atomicity of encryption context getting/setting
[fs/lustre-release.git] / lustre / llite / crypto.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2019, 2020, Whamcloud.
24  */
25 /*
26  * This file is part of Lustre, http://www.lustre.org/
27  */
28
29 #include "llite_internal.h"
30
31 #ifdef HAVE_LUSTRE_CRYPTO
32
33 static int ll_get_context(struct inode *inode, void *ctx, size_t len)
34 {
35         struct dentry *dentry;
36         int rc;
37
38         if (hlist_empty(&inode->i_dentry))
39                 return -ENODATA;
40
41         hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
42                 break;
43         }
44
45         rc = ll_vfs_getxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
46                              ctx, len);
47
48         /* used as encryption unit size */
49         if (S_ISREG(inode->i_mode))
50                 inode->i_blkbits = LUSTRE_ENCRYPTION_BLOCKBITS;
51         return rc;
52 }
53
54 int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
55                     bool preload)
56 {
57         unsigned int ext_flags;
58         int rc = 0;
59
60         /* used as encryption unit size */
61         if (S_ISREG(inode->i_mode))
62                 inode->i_blkbits = LUSTRE_ENCRYPTION_BLOCKBITS;
63         ext_flags = ll_inode_to_ext_flags(inode->i_flags) | LUSTRE_ENCRYPT_FL;
64         ll_update_inode_flags(inode, ext_flags);
65
66         if (encctx && encctxlen)
67                 rc = ll_xattr_cache_insert(inode,
68                                            LL_XATTR_NAME_ENCRYPTION_CONTEXT,
69                                            encctx, encctxlen);
70         if (rc)
71                 return rc;
72
73         return preload ? llcrypt_get_encryption_info(inode) : 0;
74 }
75
76 /* ll_set_context has 2 distinct behaviors, depending on the value of inode
77  * parameter:
78  * - inode is NULL:
79  *   passed fs_data is a struct md_op_data *. We need to store enc ctx in
80  *   op_data, so that it will be sent along to the server with the request that
81  *   the caller is preparing, thus saving a setxattr request.
82  * - inode is not NULL:
83  *   normal case in which passed fs_data is a struct dentry *, letting proceed
84  *   with setxattr operation.
85  *   This use case should only be used when explicitly setting a new encryption
86  *   policy on an existing, empty directory.
87  */
88 static int ll_set_context(struct inode *inode, const void *ctx, size_t len,
89                           void *fs_data)
90 {
91         struct dentry *dentry;
92         int rc;
93
94         if (inode == NULL) {
95                 struct md_op_data *op_data = (struct md_op_data *)fs_data;
96
97                 if (!op_data)
98                         return -EINVAL;
99
100                 OBD_ALLOC(op_data->op_file_encctx, len);
101                 if (op_data->op_file_encctx == NULL)
102                         return -ENOMEM;
103                 op_data->op_file_encctx_size = len;
104                 memcpy(op_data->op_file_encctx, ctx, len);
105                 return 0;
106         }
107
108         /* Encrypting the root directory is not allowed */
109         if (inode->i_ino == inode->i_sb->s_root->d_inode->i_ino)
110                 return -EPERM;
111
112         dentry = (struct dentry *)fs_data;
113         rc = ll_vfs_setxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
114                              ctx, len, XATTR_CREATE);
115         if (rc)
116                 return rc;
117
118         return ll_set_encflags(inode, (void *)ctx, len, false);
119 }
120
121 inline void llcrypt_free_ctx(void *encctx, __u32 size)
122 {
123         if (encctx)
124                 OBD_FREE(encctx, size);
125 }
126
127 inline bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
128 {
129         return unlikely(sbi->ll_flags & LL_SBI_TEST_DUMMY_ENCRYPTION);
130 }
131
132 static bool ll_dummy_context(struct inode *inode)
133 {
134         struct ll_sb_info *sbi = ll_i2sbi(inode);
135
136         return sbi ? ll_sbi_has_test_dummy_encryption(sbi) : false;
137 }
138
139 inline bool ll_sbi_has_encrypt(struct ll_sb_info *sbi)
140 {
141         return sbi->ll_flags & LL_SBI_ENCRYPT;
142 }
143
144 inline void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set)
145 {
146         if (set)
147                 sbi->ll_flags |= LL_SBI_ENCRYPT;
148         else
149                 sbi->ll_flags &=
150                         ~(LL_SBI_ENCRYPT | LL_SBI_TEST_DUMMY_ENCRYPTION);
151 }
152
153 static bool ll_empty_dir(struct inode *inode)
154 {
155         /* used by llcrypt_ioctl_set_policy(), because a policy can only be set
156          * on an empty dir.
157          */
158         /* Here we choose to return true, meaning we always call .set_context.
159          * Then we rely on server side, with mdd_fix_attr() that calls
160          * mdd_dir_is_empty() when setting encryption flag on directory.
161          */
162         return true;
163 }
164
165 const struct llcrypt_operations lustre_cryptops = {
166         .key_prefix             = "lustre:",
167         .get_context            = ll_get_context,
168         .set_context            = ll_set_context,
169         .dummy_context          = ll_dummy_context,
170         .empty_dir              = ll_empty_dir,
171         .max_namelen            = NAME_MAX,
172 };
173 #else /* !HAVE_LUSTRE_CRYPTO */
174 int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
175                     bool preload)
176 {
177         return 0;
178 }
179
180 inline void llcrypt_free_ctx(void *encctx, __u32 size)
181 {
182 }
183
184 inline bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
185 {
186         return false;
187 }
188
189 inline bool ll_sbi_has_encrypt(struct ll_sb_info *sbi)
190 {
191         return false;
192 }
193
194 inline void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set)
195 {
196 }
197 #endif
198