Commit db3d841a authored by Linus Torvalds's avatar Linus Torvalds

fs/pidfs: make 'lsof' happy with our inode changes

pidfs started using much saner inodes in commit b28ddcc3 ("pidfs:
convert to path_from_stashed() helper"), but that exposed the fact that
lsof had some knowledge of just how odd our old anon_inode usage was.

For example, legacy anon_inodes hadn't even initialized the inode type
in the inode mode, so everything had a type of zero.

So sane tools like 'stat' would report these files as "weird file", but
'lsof' instead used that (together with the name of the link in proc) to
notice that it's an anonymous inode, and used it to detect pidfd files.

Let's keep our internal new sane inode model, but mask the file type
bits at 'stat()' time in the getattr() function we already have, and by
making the dentry name match what lsof expects too.

This keeps our internal models sane, but should make user space see the
same old odd behavior.
Reported-by: default avatarJiri Slaby <jirislaby@kernel.org>
Link: https://lore.kernel.org/all/a15b1050-4b52-4740-a122-a4d055c17f11@kernel.org/
Link: https://github.com/lsof-org/lsof/issues/317
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Seth Forshee <sforshee@kernel.org>
Cc: Tycho Andersen <tycho@tycho.pizza>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8f6a15f0
...@@ -169,6 +169,24 @@ static int pidfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, ...@@ -169,6 +169,24 @@ static int pidfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
/*
* User space expects pidfs inodes to have no file type in st_mode.
*
* In particular, 'lsof' has this legacy logic:
*
* type = s->st_mode & S_IFMT;
* switch (type) {
* ...
* case 0:
* if (!strcmp(p, "anon_inode"))
* Lf->ntype = Ntype = N_ANON_INODE;
*
* to detect our old anon_inode logic.
*
* Rather than mess with our internal sane inode data, just fix it
* up here in getattr() by masking off the format bits.
*/
static int pidfs_getattr(struct mnt_idmap *idmap, const struct path *path, static int pidfs_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask, struct kstat *stat, u32 request_mask,
unsigned int query_flags) unsigned int query_flags)
...@@ -176,6 +194,7 @@ static int pidfs_getattr(struct mnt_idmap *idmap, const struct path *path, ...@@ -176,6 +194,7 @@ static int pidfs_getattr(struct mnt_idmap *idmap, const struct path *path,
struct inode *inode = d_inode(path->dentry); struct inode *inode = d_inode(path->dentry);
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat); generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
stat->mode &= ~S_IFMT;
return 0; return 0;
} }
...@@ -199,12 +218,13 @@ static const struct super_operations pidfs_sops = { ...@@ -199,12 +218,13 @@ static const struct super_operations pidfs_sops = {
.statfs = simple_statfs, .statfs = simple_statfs,
}; };
/*
* 'lsof' has knowledge of out historical anon_inode use, and expects
* the pidfs dentry name to start with 'anon_inode'.
*/
static char *pidfs_dname(struct dentry *dentry, char *buffer, int buflen) static char *pidfs_dname(struct dentry *dentry, char *buffer, int buflen)
{ {
struct inode *inode = d_inode(dentry); return dynamic_dname(buffer, buflen, "anon_inode:[pidfd]");
struct pid *pid = inode->i_private;
return dynamic_dname(buffer, buflen, "pidfd:[%llu]", pid->ino);
} }
static const struct dentry_operations pidfs_dentry_operations = { static const struct dentry_operations pidfs_dentry_operations = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment