File 0001-fuser-Fix-expandpath.patch of Package psmisc
From b61e3c44b636691d5d2d2519efc934eac03e0f22 Mon Sep 17 00:00:00 2001
From: Craig Small <csmall@dropbear.xyz>
Date: Sat, 3 May 2025 11:10:11 +1000
Subject: [PATCH] fuser: Fix expandpath
The function expandpath had some issues:
* It would fail if you looked at non-Unix sockets
* get_pidfd called it twice most times
* it would try to find symlinks in /proc/<PID>/fd
* it kept scanning /proc/self/net/unix over and over
This meant fuser ran really slow, and would never find
any TCP/UDP sockets (and probably anything else that wasn't
a normal file/directory or Unix socket).
The main changes are:
If we know we are looking at procfs, skip over scanning for
directories.
Use the already parsed unix sockets list
If we find a socket and its not a unix socket, return the orginal path
References:
commit 366b0071aa889d2620b78f1cf4e197771171aea8
issue #57
Signed-off-by: Craig Small <csmall@dropbear.xyz>
---
ChangeLog | 1 +
src/fuser.c | 73 +++++++++++++++++++----------------------------------
2 files changed, 27 insertions(+), 47 deletions(-)
|diff --git a/ChangeLog b/ChangeLog
|index 4222066..edf164e 100644
|--- a/ChangeLog
|+++ b/ChangeLog
|@@ -1,6 +1,7 @@
| Changes in NEXT
| ===============
| * fuser: Use mountinfo to distinguish NFS mounts !40
|+ * fuser: Make TCP/UDP sockets work again #57
| * killall,pstree: Use gettime instead of uptime Debian 1066090
| * pstree: Add -P to show path of exe !38
|
diff --git a/src/fuser.c b/src/fuser.c
index b31338e..d3622d6 100644
--- a/src/fuser.c
+++ b/src/fuser.c
@@ -134,7 +134,7 @@ static ino_t get_namespace(const pid_t pid);
static int get_mountid(const char *path);
#endif
static int find_mountpoint(const char *path, mntinfo_t **mountinfo);
-static char *expandpath(const char *path);
+static char *expandpath(const char *path, const bool isproc);
static struct unixsocket_list *unixsockets = NULL;
static struct names *names_head = NULL, *names_tail = NULL;
static struct ip_connections *tcp_connection_list = NULL;
@@ -541,7 +541,7 @@ int parse_file(
const opt_type opts)
{
mntinfo_t *mountinfo;
- char *new = expandpath(this_name->filename);
+ char *new = expandpath(this_name->filename, false);
if (new)
{
if (this_name->filename)
@@ -1722,7 +1722,7 @@ static struct stat *get_pidstat(
if (id)
{
mntinfo_t *info;
- char *new = expandpath(pathname);
+ char *new = expandpath(pathname, true);
if (new && find_mountpoint(new, &info) == 0)
*id = info->id;
else *id = -1;
@@ -2442,11 +2442,10 @@ static int get_fdinfo(
const static char delimiters[] = ": \t\n";
char line[BUFSIZ];
FILE *fp;
-# if defined(HAS_NAME_TO_HANDLE_AT)
char *realname;
-# endif
snprintf(pathname, sizeof(pathname)-1, "/proc/%d/fdinfo/%s", pid, fd);
+
if ((fp = fopen(pathname, "r")) == NULL)
goto out;
@@ -2470,9 +2469,9 @@ static int get_fdinfo(
}
fclose(fp);
out:
-# if defined(HAS_NAME_TO_HANDLE_AT)
snprintf(pathname, sizeof(pathname)-1, "/proc/%d/fd/%s", pid, fd);
- realname = expandpath(pathname);
+ realname = expandpath(pathname, true);
+# if defined(HAS_NAME_TO_HANDLE_AT)
if (realname)
{
info->mnt_id = get_mountid(realname);
@@ -2485,7 +2484,6 @@ out:
{
struct stat lst;
- snprintf(pathname, sizeof(pathname)-1, "/proc/%d/fd/%s", pid, fd);
if (!flags && lstatn(pathname, STATX_MODE, &lst) == 0)
{
if (lst.st_mode & S_IWUSR)
@@ -2495,7 +2493,6 @@ out:
if (!mnt_id)
{
- realname = expandpath(pathname);
if (realname)
{
mntinfo_t *mountinfo;
@@ -2699,7 +2696,8 @@ out:
*/
static char real[PATH_MAX + 1];
char *expandpath(
- const char *path)
+ const char *path,
+ const bool isproc)
{
char tmpbuf[PATH_MAX + 1];
const char *start, *end;
@@ -2726,7 +2724,10 @@ char *expandpath(
while (*start == '/')
++start;
- for (end = start; *end && *end != '/'; ++end) ;
+ if (isproc)
+ end = start + strlen(start);
+ else
+ for (end = start; *end && *end != '/'; ++end) ;
if (end - start == 0)
break;
@@ -2741,6 +2742,7 @@ char *expandpath(
char lnkbuf[PATH_MAX + 1];
size_t len;
ssize_t n;
+ unsigned long long lnk_inode;
if (dest[-1] != '/')
*dest++ = '/';
@@ -2773,49 +2775,26 @@ char *expandpath(
/*
* Expand to real path of named socket if any
*/
- if (lnkbuf[0] != '/' && strncmp("socket:[", lnkbuf, 8) == 0)
+ if (lnkbuf[0] != '/' && sscanf(lnkbuf, "socket:[%llu]", &lnk_inode) == 1)
{
- FILE *fp;
- char *inode;
- char line[BUFSIZ];
- if ((inode = strchr(&lnkbuf[8], ']')))
- {
- *inode = '\0';
- inode = &lnkbuf[8];
- }
-
- if (!inode || (fp = fopen(PROC_SOCKETS, "r")) == NULL)
- {
- /*fprintf(stderr, "Cannot open %s\n", PROC_SOCKETS); */
- return (char *)0;
- }
- while (fgets(line, BUFSIZ, fp) != NULL)
+ struct unixsocket_list *sock_tmp;
+ for (sock_tmp = unixsockets; sock_tmp != NULL; sock_tmp = sock_tmp->next)
{
- char *named = NULL;
- unsigned long snode;
-
- if (*line == 'N')
- continue;
-
- if (sscanf(line, "%*x: %*x %*x %*x %*x %*x %lu %ms",
- &snode, &named) == 2)
+ if (sock_tmp->net_inode == lnk_inode)
{
- char *ep;
- unsigned long oul = strtoul(inode, &ep, 0);
- if (oul == snode) {
- ep = named;
- if (*ep == '@')
- ep++;
- n = strlen(ep);
- memcpy(lnkbuf, ep, n);
- lnkbuf[n] = '\0';
- }
- free (named);
+ strncpy(lnkbuf, sock_tmp->sun_name, PATH_MAX);
+ n = strlen(sock_tmp->sun_name);
+ break;
}
}
- fclose(fp);
+ if (sock_tmp == NULL) // socket, but not unix socket
+ {
+ strcpy(real, path);
+ return curr;
+ }
}
+ lnkbuf[n] = '\0';
len = strlen(end);
if ((n + len) > PATH_MAX)
{
--
GitLab