|
24 | 24 |
|
25 | 25 | #include <linux/uaccess.h>
|
26 | 26 |
|
| 27 | +#include "internal.h" |
| 28 | + |
27 | 29 | static struct vfsmount *anon_inode_mnt __ro_after_init;
|
28 | 30 | static struct inode *anon_inode_inode __ro_after_init;
|
29 | 31 |
|
| 32 | +/* |
| 33 | + * User space expects anonymous inodes to have no file type in st_mode. |
| 34 | + * |
| 35 | + * In particular, 'lsof' has this legacy logic: |
| 36 | + * |
| 37 | + * type = s->st_mode & S_IFMT; |
| 38 | + * switch (type) { |
| 39 | + * ... |
| 40 | + * case 0: |
| 41 | + * if (!strcmp(p, "anon_inode")) |
| 42 | + * Lf->ntype = Ntype = N_ANON_INODE; |
| 43 | + * |
| 44 | + * to detect our old anon_inode logic. |
| 45 | + * |
| 46 | + * Rather than mess with our internal sane inode data, just fix it |
| 47 | + * up here in getattr() by masking off the format bits. |
| 48 | + */ |
| 49 | +int anon_inode_getattr(struct mnt_idmap *idmap, const struct path *path, |
| 50 | + struct kstat *stat, u32 request_mask, |
| 51 | + unsigned int query_flags) |
| 52 | +{ |
| 53 | + struct inode *inode = d_inode(path->dentry); |
| 54 | + |
| 55 | + generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat); |
| 56 | + stat->mode &= ~S_IFMT; |
| 57 | + return 0; |
| 58 | +} |
| 59 | + |
| 60 | +static const struct inode_operations anon_inode_operations = { |
| 61 | + .getattr = anon_inode_getattr, |
| 62 | +}; |
| 63 | + |
30 | 64 | /*
|
31 | 65 | * anon_inodefs_dname() is called from d_path().
|
32 | 66 | */
|
@@ -66,6 +100,7 @@ static struct inode *anon_inode_make_secure_inode(
|
66 | 100 | if (IS_ERR(inode))
|
67 | 101 | return inode;
|
68 | 102 | inode->i_flags &= ~S_PRIVATE;
|
| 103 | + inode->i_op = &anon_inode_operations; |
69 | 104 | error = security_inode_init_security_anon(inode, &QSTR(name),
|
70 | 105 | context_inode);
|
71 | 106 | if (error) {
|
@@ -313,6 +348,7 @@ static int __init anon_inode_init(void)
|
313 | 348 | anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
|
314 | 349 | if (IS_ERR(anon_inode_inode))
|
315 | 350 | panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode));
|
| 351 | + anon_inode_inode->i_op = &anon_inode_operations; |
316 | 352 |
|
317 | 353 | return 0;
|
318 | 354 | }
|
|
0 commit comments