|
1 | 1 | // SPDX-License-Identifier: GPL-2.0
|
2 | 2 | #include <linux/anon_inodes.h>
|
| 3 | +#include <linux/exportfs.h> |
3 | 4 | #include <linux/file.h>
|
4 | 5 | #include <linux/fs.h>
|
5 | 6 | #include <linux/cgroup.h>
|
@@ -473,6 +474,118 @@ static const struct dentry_operations pidfs_dentry_operations = {
|
473 | 474 | .d_prune = stashed_dentry_prune,
|
474 | 475 | };
|
475 | 476 |
|
| 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 | + |
476 | 589 | static int pidfs_init_inode(struct inode *inode, void *data)
|
477 | 590 | {
|
478 | 591 | const struct pid *pid = data;
|
@@ -507,6 +620,7 @@ static int pidfs_init_fs_context(struct fs_context *fc)
|
507 | 620 | return -ENOMEM;
|
508 | 621 |
|
509 | 622 | ctx->ops = &pidfs_sops;
|
| 623 | + ctx->eops = &pidfs_export_operations; |
510 | 624 | ctx->dops = &pidfs_dentry_operations;
|
511 | 625 | fc->s_fs_info = (void *)&pidfs_stashed_ops;
|
512 | 626 | return 0;
|
|
0 commit comments