Skip to content

Commit 8297b79

Browse files
committed
Merge tag 'pull-securityfs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull securityfs updates from Al Viro: "Securityfs cleanups and fixes: - one extra reference is enough to pin a dentry down; no need for two. Switch to regular scheme, similar to shmem, debugfs, etc. This fixes a securityfs_recursive_remove() dentry leak, among other things. - we need to have the filesystem pinned to prevent the contents disappearing; what we do not need is pinning it for each file. Doing that only for files and directories in the root is enough. - the previous two changes allow us to get rid of the racy kludges in efi_secret_unlink(), where we can use simple_unlink() instead of securityfs_remove(). Which does not require unlocking and relocking the parent, with all deadlocks that invites. - Make securityfs_remove() take the entire subtree out, turning securityfs_recursive_remove() into its alias. Makes a lot more sense for callers and fixes a mount leak, while we are at it. - Making securityfs_remove() remove the entire subtree allows for much simpler life in most of the users - efi_secret, ima_fs, evm, ipe, tmp get cleaner. I hadn't touched apparmor use of securityfs, but I suspect that it would be useful there as well" * tag 'pull-securityfs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: tpm: don't bother with removal of files in directory we'll be removing ipe: don't bother with removal of files in directory we'll be removing evm_secfs: clear securityfs interactions ima_fs: get rid of lookup-by-dentry stuff ima_fs: don't bother with removal of files in directory we'll be removing efi_secret: clean securityfs use up make securityfs_remove() remove the entire subtree fix locking in efi_secret_unlink() securityfs: pin filesystem only for objects directly in root securityfs: don't pin dentries twice, once is enough...
2 parents ddf52f1 + f42b8d7 commit 8297b79

9 files changed

Lines changed: 97 additions & 251 deletions

File tree

drivers/char/tpm/eventlog/common.c

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static int tpm_bios_measurements_open(struct inode *inode,
3232
struct tpm_chip *chip;
3333

3434
inode_lock(inode);
35-
if (!inode->i_private) {
35+
if (!inode->i_nlink) {
3636
inode_unlock(inode);
3737
return -ENODEV;
3838
}
@@ -105,7 +105,7 @@ static int tpm_read_log(struct tpm_chip *chip)
105105
void tpm_bios_log_setup(struct tpm_chip *chip)
106106
{
107107
const char *name = dev_name(&chip->dev);
108-
unsigned int cnt;
108+
struct dentry *dentry;
109109
int log_version;
110110
int rc = 0;
111111

@@ -117,14 +117,12 @@ void tpm_bios_log_setup(struct tpm_chip *chip)
117117
return;
118118
log_version = rc;
119119

120-
cnt = 0;
121-
chip->bios_dir[cnt] = securityfs_create_dir(name, NULL);
120+
chip->bios_dir = securityfs_create_dir(name, NULL);
122121
/* NOTE: securityfs_create_dir can return ENODEV if securityfs is
123122
* compiled out. The caller should ignore the ENODEV return code.
124123
*/
125-
if (IS_ERR(chip->bios_dir[cnt]))
126-
goto err;
127-
cnt++;
124+
if (IS_ERR(chip->bios_dir))
125+
return;
128126

129127
chip->bin_log_seqops.chip = chip;
130128
if (log_version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
@@ -135,57 +133,37 @@ void tpm_bios_log_setup(struct tpm_chip *chip)
135133
&tpm1_binary_b_measurements_seqops;
136134

137135

138-
chip->bios_dir[cnt] =
136+
dentry =
139137
securityfs_create_file("binary_bios_measurements",
140-
0440, chip->bios_dir[0],
138+
0440, chip->bios_dir,
141139
(void *)&chip->bin_log_seqops,
142140
&tpm_bios_measurements_ops);
143-
if (IS_ERR(chip->bios_dir[cnt]))
141+
if (IS_ERR(dentry))
144142
goto err;
145-
cnt++;
146143

147144
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
148145

149146
chip->ascii_log_seqops.chip = chip;
150147
chip->ascii_log_seqops.seqops =
151148
&tpm1_ascii_b_measurements_seqops;
152149

153-
chip->bios_dir[cnt] =
150+
dentry =
154151
securityfs_create_file("ascii_bios_measurements",
155-
0440, chip->bios_dir[0],
152+
0440, chip->bios_dir,
156153
(void *)&chip->ascii_log_seqops,
157154
&tpm_bios_measurements_ops);
158-
if (IS_ERR(chip->bios_dir[cnt]))
155+
if (IS_ERR(dentry))
159156
goto err;
160-
cnt++;
161157
}
162158

163159
return;
164160

165161
err:
166-
chip->bios_dir[cnt] = NULL;
167162
tpm_bios_log_teardown(chip);
168163
return;
169164
}
170165

171166
void tpm_bios_log_teardown(struct tpm_chip *chip)
172167
{
173-
int i;
174-
struct inode *inode;
175-
176-
/* securityfs_remove currently doesn't take care of handling sync
177-
* between removal and opening of pseudo files. To handle this, a
178-
* workaround is added by making i_private = NULL here during removal
179-
* and to check it during open(), both within inode_lock()/unlock().
180-
* This design ensures that open() either safely gets kref or fails.
181-
*/
182-
for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) {
183-
if (chip->bios_dir[i]) {
184-
inode = d_inode(chip->bios_dir[i]);
185-
inode_lock(inode);
186-
inode->i_private = NULL;
187-
inode_unlock(inode);
188-
securityfs_remove(chip->bios_dir[i]);
189-
}
190-
}
168+
securityfs_remove(chip->bios_dir);
191169
}

drivers/virt/coco/efi_secret/efi_secret.c

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131

3232
struct efi_secret {
3333
struct dentry *secrets_dir;
34-
struct dentry *fs_dir;
35-
struct dentry *fs_files[EFI_SECRET_NUM_FILES];
3634
void __iomem *secret_data;
3735
u64 secret_data_len;
3836
};
@@ -119,10 +117,8 @@ static void wipe_memory(void *addr, size_t size)
119117

120118
static int efi_secret_unlink(struct inode *dir, struct dentry *dentry)
121119
{
122-
struct efi_secret *s = efi_secret_get();
123120
struct inode *inode = d_inode(dentry);
124121
struct secret_entry *e = (struct secret_entry *)inode->i_private;
125-
int i;
126122

127123
if (e) {
128124
/* Zero out the secret data */
@@ -132,19 +128,7 @@ static int efi_secret_unlink(struct inode *dir, struct dentry *dentry)
132128

133129
inode->i_private = NULL;
134130

135-
for (i = 0; i < EFI_SECRET_NUM_FILES; i++)
136-
if (s->fs_files[i] == dentry)
137-
s->fs_files[i] = NULL;
138-
139-
/*
140-
* securityfs_remove tries to lock the directory's inode, but we reach
141-
* the unlink callback when it's already locked
142-
*/
143-
inode_unlock(dir);
144-
securityfs_remove(dentry);
145-
inode_lock(dir);
146-
147-
return 0;
131+
return simple_unlink(inode, dentry);
148132
}
149133

150134
static const struct inode_operations efi_secret_dir_inode_operations = {
@@ -194,15 +178,6 @@ static int efi_secret_map_area(struct platform_device *dev)
194178
static void efi_secret_securityfs_teardown(struct platform_device *dev)
195179
{
196180
struct efi_secret *s = efi_secret_get();
197-
int i;
198-
199-
for (i = (EFI_SECRET_NUM_FILES - 1); i >= 0; i--) {
200-
securityfs_remove(s->fs_files[i]);
201-
s->fs_files[i] = NULL;
202-
}
203-
204-
securityfs_remove(s->fs_dir);
205-
s->fs_dir = NULL;
206181

207182
securityfs_remove(s->secrets_dir);
208183
s->secrets_dir = NULL;
@@ -217,7 +192,7 @@ static int efi_secret_securityfs_setup(struct platform_device *dev)
217192
unsigned char *ptr;
218193
struct secret_header *h;
219194
struct secret_entry *e;
220-
struct dentry *dent;
195+
struct dentry *dent, *dir;
221196
char guid_str[EFI_VARIABLE_GUID_LEN + 1];
222197

223198
ptr = (void __force *)s->secret_data;
@@ -240,8 +215,6 @@ static int efi_secret_securityfs_setup(struct platform_device *dev)
240215
}
241216

242217
s->secrets_dir = NULL;
243-
s->fs_dir = NULL;
244-
memset(s->fs_files, 0, sizeof(s->fs_files));
245218

246219
dent = securityfs_create_dir("secrets", NULL);
247220
if (IS_ERR(dent)) {
@@ -251,14 +224,13 @@ static int efi_secret_securityfs_setup(struct platform_device *dev)
251224
}
252225
s->secrets_dir = dent;
253226

254-
dent = securityfs_create_dir("coco", s->secrets_dir);
255-
if (IS_ERR(dent)) {
227+
dir = securityfs_create_dir("coco", s->secrets_dir);
228+
if (IS_ERR(dir)) {
256229
dev_err(&dev->dev, "Error creating coco securityfs directory entry err=%ld\n",
257-
PTR_ERR(dent));
258-
return PTR_ERR(dent);
230+
PTR_ERR(dir));
231+
return PTR_ERR(dir);
259232
}
260-
d_inode(dent)->i_op = &efi_secret_dir_inode_operations;
261-
s->fs_dir = dent;
233+
d_inode(dir)->i_op = &efi_secret_dir_inode_operations;
262234

263235
bytes_left = h->len - sizeof(*h);
264236
ptr += sizeof(*h);
@@ -274,15 +246,14 @@ static int efi_secret_securityfs_setup(struct platform_device *dev)
274246
if (efi_guidcmp(e->guid, NULL_GUID)) {
275247
efi_guid_to_str(&e->guid, guid_str);
276248

277-
dent = securityfs_create_file(guid_str, 0440, s->fs_dir, (void *)e,
249+
dent = securityfs_create_file(guid_str, 0440, dir, (void *)e,
278250
&efi_secret_bin_file_fops);
279251
if (IS_ERR(dent)) {
280252
dev_err(&dev->dev, "Error creating efi_secret securityfs entry\n");
281253
ret = PTR_ERR(dent);
282254
goto err_cleanup;
283255
}
284-
285-
s->fs_files[i++] = dent;
256+
i++;
286257
}
287258
ptr += e->len;
288259
bytes_left -= e->len;

include/linux/security.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2211,7 +2211,6 @@ struct dentry *securityfs_create_symlink(const char *name,
22112211
const char *target,
22122212
const struct inode_operations *iops);
22132213
extern void securityfs_remove(struct dentry *dentry);
2214-
extern void securityfs_recursive_remove(struct dentry *dentry);
22152214

22162215
#else /* CONFIG_SECURITYFS */
22172216

@@ -2243,6 +2242,8 @@ static inline void securityfs_remove(struct dentry *dentry)
22432242

22442243
#endif
22452244

2245+
#define securityfs_recursive_remove securityfs_remove
2246+
22462247
#ifdef CONFIG_BPF_SYSCALL
22472248
union bpf_attr;
22482249
struct bpf_map;

include/linux/tpm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ struct tpm_chip {
182182
unsigned long duration[TPM_NUM_DURATIONS]; /* jiffies */
183183
bool duration_adjusted;
184184

185-
struct dentry *bios_dir[TPM_NUM_EVENT_LOG_FILES];
185+
struct dentry *bios_dir;
186186

187187
const struct attribute_group *groups[3 + TPM_MAX_HASHES];
188188
unsigned int groups_cnt;

security/inode.c

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -112,18 +112,20 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
112112
struct dentry *dentry;
113113
struct inode *dir, *inode;
114114
int error;
115+
bool pinned = false;
115116

116117
if (!(mode & S_IFMT))
117118
mode = (mode & S_IALLUGO) | S_IFREG;
118119

119120
pr_debug("securityfs: creating file '%s'\n",name);
120121

121-
error = simple_pin_fs(&fs_type, &mount, &mount_count);
122-
if (error)
123-
return ERR_PTR(error);
124-
125-
if (!parent)
122+
if (!parent) {
123+
error = simple_pin_fs(&fs_type, &mount, &mount_count);
124+
if (error)
125+
return ERR_PTR(error);
126+
pinned = true;
126127
parent = mount->mnt_root;
128+
}
127129

128130
dir = d_inode(parent);
129131

@@ -159,7 +161,6 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
159161
inode->i_fop = fops;
160162
}
161163
d_instantiate(dentry, inode);
162-
dget(dentry);
163164
inode_unlock(dir);
164165
return dentry;
165166

@@ -168,7 +169,8 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
168169
dentry = ERR_PTR(error);
169170
out:
170171
inode_unlock(dir);
171-
simple_release_fs(&mount, &mount_count);
172+
if (pinned)
173+
simple_release_fs(&mount, &mount_count);
172174
return dentry;
173175
}
174176

@@ -279,6 +281,12 @@ struct dentry *securityfs_create_symlink(const char *name,
279281
}
280282
EXPORT_SYMBOL_GPL(securityfs_create_symlink);
281283

284+
static void remove_one(struct dentry *victim)
285+
{
286+
if (victim->d_parent == victim->d_sb->s_root)
287+
simple_release_fs(&mount, &mount_count);
288+
}
289+
282290
/**
283291
* securityfs_remove - removes a file or directory from the securityfs filesystem
284292
*
@@ -291,43 +299,11 @@ EXPORT_SYMBOL_GPL(securityfs_create_symlink);
291299
* This function is required to be called in order for the file to be
292300
* removed. No automatic cleanup of files will happen when a module is
293301
* removed; you are responsible here.
294-
*/
295-
void securityfs_remove(struct dentry *dentry)
296-
{
297-
struct inode *dir;
298-
299-
if (IS_ERR_OR_NULL(dentry))
300-
return;
301-
302-
dir = d_inode(dentry->d_parent);
303-
inode_lock(dir);
304-
if (simple_positive(dentry)) {
305-
if (d_is_dir(dentry))
306-
simple_rmdir(dir, dentry);
307-
else
308-
simple_unlink(dir, dentry);
309-
dput(dentry);
310-
}
311-
inode_unlock(dir);
312-
simple_release_fs(&mount, &mount_count);
313-
}
314-
EXPORT_SYMBOL_GPL(securityfs_remove);
315-
316-
static void remove_one(struct dentry *victim)
317-
{
318-
simple_release_fs(&mount, &mount_count);
319-
}
320-
321-
/**
322-
* securityfs_recursive_remove - recursively removes a file or directory
323-
*
324-
* @dentry: a pointer to a the dentry of the file or directory to be removed.
325302
*
326-
* This function recursively removes a file or directory in securityfs that was
327-
* previously created with a call to another securityfs function (like
328-
* securityfs_create_file() or variants thereof.)
303+
* AV: when applied to directory it will take all children out; no need to call
304+
* it for descendents if ancestor is getting killed.
329305
*/
330-
void securityfs_recursive_remove(struct dentry *dentry)
306+
void securityfs_remove(struct dentry *dentry)
331307
{
332308
if (IS_ERR_OR_NULL(dentry))
333309
return;
@@ -336,7 +312,7 @@ void securityfs_recursive_remove(struct dentry *dentry)
336312
simple_recursive_removal(dentry, remove_one);
337313
simple_release_fs(&mount, &mount_count);
338314
}
339-
EXPORT_SYMBOL_GPL(securityfs_recursive_remove);
315+
EXPORT_SYMBOL_GPL(securityfs_remove);
340316

341317
#ifdef CONFIG_SECURITY
342318
static struct dentry *lsm_dentry;

0 commit comments

Comments
 (0)