Skip to content

Commit c1298a3

Browse files
committed
big_keys: Use struct for internal payload
The randstruct GCC plugin gets upset when it sees struct path (which is randomized) being assigned from a "void *" (which it cannot type-check). There's no need for these casts, as the entire internal payload use is following a normal struct layout. Convert the enum-based void * offset dereferencing to the new big_key_payload struct. No meaningful machine code changes result after this change, and source readability is improved. Drop the randstruct exception now that there is no "confusing" cross-type assignment. Cc: David Howells <[email protected]> Cc: Eric Biggers <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Jarkko Sakkinen <[email protected]> Cc: James Morris <[email protected]> Cc: "Serge E. Hallyn" <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent 61f60ba commit c1298a3

File tree

2 files changed

+36
-39
lines changed

2 files changed

+36
-39
lines changed

scripts/gcc-plugins/randomize_layout_plugin.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ static const struct whitelist_entry whitelist[] = {
5050
{ "drivers/net/ethernet/sun/niu.c", "page", "address_space" },
5151
/* unix_skb_parms via UNIXCB() buffer */
5252
{ "net/unix/af_unix.c", "unix_skb_parms", "char" },
53-
/* big_key payload.data struct splashing */
54-
{ "security/keys/big_key.c", "path", "void *" },
5553
{ }
5654
};
5755

security/keys/big_key.c

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020
/*
2121
* Layout of key payload words.
2222
*/
23-
enum {
24-
big_key_data,
25-
big_key_path,
26-
big_key_path_2nd_part,
27-
big_key_len,
23+
struct big_key_payload {
24+
u8 *data;
25+
struct path path;
26+
size_t length;
2827
};
28+
#define to_big_key_payload(payload) \
29+
(struct big_key_payload *)((payload).data)
2930

3031
/*
3132
* If the data is under this limit, there's no point creating a shm file to
@@ -55,21 +56,23 @@ struct key_type key_type_big_key = {
5556
*/
5657
int big_key_preparse(struct key_preparsed_payload *prep)
5758
{
58-
struct path *path = (struct path *)&prep->payload.data[big_key_path];
59+
struct big_key_payload *payload = to_big_key_payload(prep->payload);
5960
struct file *file;
6061
u8 *buf, *enckey;
6162
ssize_t written;
6263
size_t datalen = prep->datalen;
6364
size_t enclen = datalen + CHACHA20POLY1305_AUTHTAG_SIZE;
6465
int ret;
6566

67+
BUILD_BUG_ON(sizeof(*payload) != sizeof(prep->payload.data));
68+
6669
if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data)
6770
return -EINVAL;
6871

6972
/* Set an arbitrary quota */
7073
prep->quotalen = 16;
7174

72-
prep->payload.data[big_key_len] = (void *)(unsigned long)datalen;
75+
payload->length = datalen;
7376

7477
if (datalen > BIG_KEY_FILE_THRESHOLD) {
7578
/* Create a shmem file to store the data in. This will permit the data
@@ -117,9 +120,9 @@ int big_key_preparse(struct key_preparsed_payload *prep)
117120
/* Pin the mount and dentry to the key so that we can open it again
118121
* later
119122
*/
120-
prep->payload.data[big_key_data] = enckey;
121-
*path = file->f_path;
122-
path_get(path);
123+
payload->data = enckey;
124+
payload->path = file->f_path;
125+
path_get(&payload->path);
123126
fput(file);
124127
kvfree_sensitive(buf, enclen);
125128
} else {
@@ -129,7 +132,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
129132
if (!data)
130133
return -ENOMEM;
131134

132-
prep->payload.data[big_key_data] = data;
135+
payload->data = data;
133136
memcpy(data, prep->data, prep->datalen);
134137
}
135138
return 0;
@@ -148,12 +151,11 @@ int big_key_preparse(struct key_preparsed_payload *prep)
148151
*/
149152
void big_key_free_preparse(struct key_preparsed_payload *prep)
150153
{
151-
if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
152-
struct path *path = (struct path *)&prep->payload.data[big_key_path];
154+
struct big_key_payload *payload = to_big_key_payload(prep->payload);
153155

154-
path_put(path);
155-
}
156-
kfree_sensitive(prep->payload.data[big_key_data]);
156+
if (prep->datalen > BIG_KEY_FILE_THRESHOLD)
157+
path_put(&payload->path);
158+
kfree_sensitive(payload->data);
157159
}
158160

159161
/*
@@ -162,31 +164,28 @@ void big_key_free_preparse(struct key_preparsed_payload *prep)
162164
*/
163165
void big_key_revoke(struct key *key)
164166
{
165-
struct path *path = (struct path *)&key->payload.data[big_key_path];
167+
struct big_key_payload *payload = to_big_key_payload(key->payload);
166168

167169
/* clear the quota */
168170
key_payload_reserve(key, 0);
169-
if (key_is_positive(key) &&
170-
(size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
171-
vfs_truncate(path, 0);
171+
if (key_is_positive(key) && payload->length > BIG_KEY_FILE_THRESHOLD)
172+
vfs_truncate(&payload->path, 0);
172173
}
173174

174175
/*
175176
* dispose of the data dangling from the corpse of a big_key key
176177
*/
177178
void big_key_destroy(struct key *key)
178179
{
179-
size_t datalen = (size_t)key->payload.data[big_key_len];
180-
181-
if (datalen > BIG_KEY_FILE_THRESHOLD) {
182-
struct path *path = (struct path *)&key->payload.data[big_key_path];
180+
struct big_key_payload *payload = to_big_key_payload(key->payload);
183181

184-
path_put(path);
185-
path->mnt = NULL;
186-
path->dentry = NULL;
182+
if (payload->length > BIG_KEY_FILE_THRESHOLD) {
183+
path_put(&payload->path);
184+
payload->path.mnt = NULL;
185+
payload->path.dentry = NULL;
187186
}
188-
kfree_sensitive(key->payload.data[big_key_data]);
189-
key->payload.data[big_key_data] = NULL;
187+
kfree_sensitive(payload->data);
188+
payload->data = NULL;
190189
}
191190

192191
/*
@@ -211,14 +210,14 @@ int big_key_update(struct key *key, struct key_preparsed_payload *prep)
211210
*/
212211
void big_key_describe(const struct key *key, struct seq_file *m)
213212
{
214-
size_t datalen = (size_t)key->payload.data[big_key_len];
213+
struct big_key_payload *payload = to_big_key_payload(key->payload);
215214

216215
seq_puts(m, key->description);
217216

218217
if (key_is_positive(key))
219218
seq_printf(m, ": %zu [%s]",
220-
datalen,
221-
datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
219+
payload->length,
220+
payload->length > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
222221
}
223222

224223
/*
@@ -227,24 +226,24 @@ void big_key_describe(const struct key *key, struct seq_file *m)
227226
*/
228227
long big_key_read(const struct key *key, char *buffer, size_t buflen)
229228
{
230-
size_t datalen = (size_t)key->payload.data[big_key_len];
229+
struct big_key_payload *payload = to_big_key_payload(key->payload);
230+
size_t datalen = payload->length;
231231
long ret;
232232

233233
if (!buffer || buflen < datalen)
234234
return datalen;
235235

236236
if (datalen > BIG_KEY_FILE_THRESHOLD) {
237-
struct path *path = (struct path *)&key->payload.data[big_key_path];
238237
struct file *file;
239-
u8 *buf, *enckey = (u8 *)key->payload.data[big_key_data];
238+
u8 *buf, *enckey = payload->data;
240239
size_t enclen = datalen + CHACHA20POLY1305_AUTHTAG_SIZE;
241240
loff_t pos = 0;
242241

243242
buf = kvmalloc(enclen, GFP_KERNEL);
244243
if (!buf)
245244
return -ENOMEM;
246245

247-
file = dentry_open(path, O_RDONLY, current_cred());
246+
file = dentry_open(&payload->path, O_RDONLY, current_cred());
248247
if (IS_ERR(file)) {
249248
ret = PTR_ERR(file);
250249
goto error;
@@ -274,7 +273,7 @@ long big_key_read(const struct key *key, char *buffer, size_t buflen)
274273
kvfree_sensitive(buf, enclen);
275274
} else {
276275
ret = datalen;
277-
memcpy(buffer, key->payload.data[big_key_data], datalen);
276+
memcpy(buffer, payload->data, datalen);
278277
}
279278

280279
return ret;

0 commit comments

Comments
 (0)