Merge pull request #31713 from YHNdnzj/pidref-equal

pidref: use fd_inode_same to compare pidfds
This commit is contained in:
Mike Yuan 2024-03-12 14:15:36 +08:00 committed by GitHub
commit 18eebde33a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 33 additions and 15 deletions

View file

@ -8,6 +8,33 @@
#include "pidref.h"
#include "process-util.h"
#include "signal-util.h"
#include "stat-util.h"
bool pidref_equal(const PidRef *a, const PidRef *b) {
int r;
if (pidref_is_set(a)) {
if (!pidref_is_set(b))
return false;
if (a->pid != b->pid)
return false;
if (a->fd < 0 || b->fd < 0)
return true;
/* pidfds live in their own pidfs and each process comes with a unique inode number since
* kernel 6.8. We can safely do this on older kernels too though, as previously anonymous
* inode was used and inode number was the same for all pidfds. */
r = fd_inode_same(a->fd, b->fd);
if (r < 0)
log_debug_errno(r, "Failed to check whether pidfds for pid " PID_FMT " are equal, assuming yes: %m",
a->pid);
return r != 0;
}
return !pidref_is_set(b);
}
int pidref_set_pid(PidRef *pidref, pid_t pid) {
int fd;

View file

@ -19,17 +19,7 @@ static inline bool pidref_is_set(const PidRef *pidref) {
return pidref && pidref->pid > 0;
}
static inline bool pidref_equal(const PidRef *a, const PidRef *b) {
if (pidref_is_set(a)) {
if (!pidref_is_set(b))
return false;
return a->pid == b->pid;
}
return !pidref_is_set(b);
}
bool pidref_equal(const PidRef *a, const PidRef *b);
/* This turns a pid_t into a PidRef structure, and acquires a pidfd for it, if possible. (As opposed to
* PIDREF_MAKE_FROM_PID() above, which does not acquire a pidfd.) */

View file

@ -365,7 +365,7 @@ bool stat_inode_same(const struct stat *a, const struct stat *b) {
* a thorough check, comparing inode nr, backing device and if the inode is still of the same type. */
return a && b &&
(a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */
a->st_dev != 0 && /* is the structure ever initialized? */
((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */
a->st_dev == b->st_dev &&
a->st_ino == b->st_ino;
@ -395,7 +395,6 @@ bool statx_inode_same(const struct statx *a, const struct statx *b) {
return a && b &&
FLAGS_SET(a->stx_mask, STATX_TYPE|STATX_INO) && FLAGS_SET(b->stx_mask, STATX_TYPE|STATX_INO) &&
(a->stx_mode & S_IFMT) != 0 &&
((a->stx_mode ^ b->stx_mode) & S_IFMT) == 0 &&
a->stx_dev_major == b->stx_dev_major &&
a->stx_dev_minor == b->stx_dev_minor &&

View file

@ -47,10 +47,12 @@ static inline int null_or_empty_path(const char *fn) {
int path_is_read_only_fs(const char *path);
int inode_same_at(int fda, const char *filea, int fdb, const char *fileb, int flags);
static inline int inode_same(const char *filea, const char *fileb, int flags) {
return inode_same_at(AT_FDCWD, filea, AT_FDCWD, fileb, flags);
}
static inline int fd_inode_same(int fda, int fdb) {
return inode_same_at(fda, NULL, fdb, NULL, AT_EMPTY_PATH);
}
/* The .f_type field of struct statfs is really weird defined on
* different archs. Let's give its type a name. */

View file

@ -884,7 +884,7 @@ int pty_forward_new(
assert(f->input_fd >= 0);
same = inode_same_at(f->input_fd, NULL, f->output_fd, NULL, AT_EMPTY_PATH);
same = fd_inode_same(f->input_fd, f->output_fd);
if (same < 0)
return same;