Skip to content

Commit b3caba8

Browse files
committed
pidfs: implement file handle support
On 64-bit platforms, userspace can read the pidfd's inode in order to get a never-repeated PID identifier. On 32-bit platforms this identifier is not exposed, as inodes are limited to 32 bits. Instead expose the identifier via export_fh, which makes it available to userspace via name_to_handle_at. In addition we implement fh_to_dentry, which allows userspace to recover a pidfd from a pidfs file handle. Signed-off-by: Erin Shepherd <[email protected]> [brauner: patch heavily rewritten] Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Amir Goldstein <[email protected]> Co-Developed-by: Christian Brauner <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent c220e21 commit b3caba8

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

fs/pidfs.c

+114
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <linux/anon_inodes.h>
3+
#include <linux/exportfs.h>
34
#include <linux/file.h>
45
#include <linux/fs.h>
56
#include <linux/cgroup.h>
@@ -473,6 +474,118 @@ static const struct dentry_operations pidfs_dentry_operations = {
473474
.d_prune = stashed_dentry_prune,
474475
};
475476

477+
static int pidfs_encode_fh(struct inode *inode, u32 *fh, int *max_len,
478+
struct inode *parent)
479+
{
480+
const struct pid *pid = inode->i_private;
481+
482+
if (*max_len < 2) {
483+
*max_len = 2;
484+
return FILEID_INVALID;
485+
}
486+
487+
*max_len = 2;
488+
*(u64 *)fh = pid->ino;
489+
return FILEID_KERNFS;
490+
}
491+
492+
/* Find a struct pid based on the inode number. */
493+
static struct pid *pidfs_ino_get_pid(u64 ino)
494+
{
495+
unsigned long pid_ino = pidfs_ino(ino);
496+
u32 gen = pidfs_gen(ino);
497+
struct pid *pid;
498+
499+
guard(rcu)();
500+
501+
pid = idr_find(&pidfs_ino_idr, lower_32_bits(pid_ino));
502+
if (!pid)
503+
return NULL;
504+
505+
if (pidfs_ino(pid->ino) != pid_ino)
506+
return NULL;
507+
508+
if (pidfs_gen(pid->ino) != gen)
509+
return NULL;
510+
511+
/* Within our pid namespace hierarchy? */
512+
if (pid_vnr(pid) == 0)
513+
return NULL;
514+
515+
return get_pid(pid);
516+
}
517+
518+
static struct dentry *pidfs_fh_to_dentry(struct super_block *sb,
519+
struct fid *fid, int fh_len,
520+
int fh_type)
521+
{
522+
int ret;
523+
u64 pid_ino;
524+
struct path path;
525+
struct pid *pid;
526+
527+
if (fh_len < 2)
528+
return NULL;
529+
530+
switch (fh_type) {
531+
case FILEID_KERNFS:
532+
pid_ino = *(u64 *)fid;
533+
break;
534+
default:
535+
return NULL;
536+
}
537+
538+
pid = pidfs_ino_get_pid(pid_ino);
539+
if (!pid)
540+
return NULL;
541+
542+
ret = path_from_stashed(&pid->stashed, pidfs_mnt, pid, &path);
543+
if (ret < 0)
544+
return ERR_PTR(ret);
545+
546+
mntput(path.mnt);
547+
return path.dentry;
548+
}
549+
550+
/*
551+
* Make sure that we reject any nonsensical flags that users pass via
552+
* open_by_handle_at(). Note that PIDFD_THREAD is defined as O_EXCL, and
553+
* PIDFD_NONBLOCK as O_NONBLOCK.
554+
*/
555+
#define VALID_FILE_HANDLE_OPEN_FLAGS \
556+
(O_RDONLY | O_WRONLY | O_RDWR | O_NONBLOCK | O_CLOEXEC | O_EXCL)
557+
558+
static int pidfs_export_permission(struct handle_to_path_ctx *ctx,
559+
unsigned int oflags)
560+
{
561+
if (oflags & ~(VALID_FILE_HANDLE_OPEN_FLAGS | O_LARGEFILE))
562+
return -EINVAL;
563+
564+
/*
565+
* pidfd_ino_get_pid() will verify that the struct pid is part
566+
* of the caller's pid namespace hierarchy. No further
567+
* permission checks are needed.
568+
*/
569+
return 0;
570+
}
571+
572+
static struct file *pidfs_export_open(struct path *path, unsigned int oflags)
573+
{
574+
/*
575+
* Clear O_LARGEFILE as open_by_handle_at() forces it and raise
576+
* O_RDWR as pidfds always are.
577+
*/
578+
oflags &= ~O_LARGEFILE;
579+
return dentry_open(path, oflags | O_RDWR, current_cred());
580+
}
581+
582+
static const struct export_operations pidfs_export_operations = {
583+
.encode_fh = pidfs_encode_fh,
584+
.fh_to_dentry = pidfs_fh_to_dentry,
585+
.open = pidfs_export_open,
586+
.permission = pidfs_export_permission,
587+
};
588+
476589
static int pidfs_init_inode(struct inode *inode, void *data)
477590
{
478591
const struct pid *pid = data;
@@ -507,6 +620,7 @@ static int pidfs_init_fs_context(struct fs_context *fc)
507620
return -ENOMEM;
508621

509622
ctx->ops = &pidfs_sops;
623+
ctx->eops = &pidfs_export_operations;
510624
ctx->dops = &pidfs_dentry_operations;
511625
fc->s_fs_info = (void *)&pidfs_stashed_ops;
512626
return 0;

0 commit comments

Comments
 (0)