diff --git a/0001-Use-mountinfo-to-be-able-to-use-the-mount-identity.patch b/0001-Use-mountinfo-to-be-able-to-use-the-mount-identity.patch index 3b8c06e..e734897 100644 --- a/0001-Use-mountinfo-to-be-able-to-use-the-mount-identity.patch +++ b/0001-Use-mountinfo-to-be-able-to-use-the-mount-identity.patch @@ -1,6 +1,6 @@ -From bfa17afa43fc1b98c2bbc9c54416db9ccb505028 Mon Sep 17 00:00:00 2001 +From e5d42c39541c94c00d97ed490add24bc898ebe0a Mon Sep 17 00:00:00 2001 From: Werner Fink -Date: Fri, 7 May 2021 16:25:13 +0200 +Date: Wed, 13 Jan 2021 11:59:24 +0100 Subject: [PATCH] Use mountinfo to be able to use the mount identity which allows to distinguish different mounts with the @@ -19,19 +19,16 @@ Allow not unique mounts as well as not unique mountpoint Fuser does not show open kvm storage image files such as qcow2 files. Patch from Ali Abdallah -Correct last change by using our own namespace to -determine the appropriate mount ID for e.g. qcow2 files. - Signed-off-by: Werner Fink --- configure.ac | 15 + - src/fuser.c | 681 +++++++++++++++++++++++++++++++++++++++++++++------------- + src/fuser.c | 646 ++++++++++++++++++++++++++++++++++++++++++++-------------- src/fuser.h | 27 +- src/timeout.c | 5 - 4 files changed, 567 insertions(+), 161 deletions(-) + 4 files changed, 534 insertions(+), 159 deletions(-) --- configure.ac -+++ configure.ac 2021-05-07 15:01:31.910757814 +0000 ++++ configure.ac 2021-03-05 13:57:45.175585808 +0000 @@ -44,6 +44,19 @@ if test "$enable_timeout_stat" = "static fi AM_CONDITIONAL([WANT_TIMEOUT_STAT], [test "$enable_timeout_stat" = "static"]) @@ -62,17 +59,19 @@ Signed-off-by: Werner Fink dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST --- src/fuser.c -+++ src/fuser.c 2021-05-07 15:03:42.232365037 +0000 -@@ -32,6 +32,8 @@ ++++ src/fuser.c 2021-03-05 14:03:20.189518326 +0000 +@@ -32,6 +32,10 @@ #include #include #include +#include ++#if defined(HAS_GETFH) +#include ++#endif #include #include #include -@@ -79,7 +81,7 @@ static void check_map(const pid_t pid, c +@@ -79,7 +83,7 @@ static void check_map(const pid_t pid, c struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access); @@ -81,7 +80,7 @@ Signed-off-by: Werner Fink static uid_t getpiduid(const pid_t pid); static int print_matches(struct names *names_head, const opt_type opts, const int sig_number); -@@ -88,9 +90,9 @@ static int kill_matched_proc(struct proc +@@ -88,9 +92,9 @@ static int kill_matched_proc(struct proc /*int parse_mount(struct names *this_name, struct device_list **dev_list);*/ static void add_device(struct device_list **dev_list, @@ -94,7 +93,7 @@ Signed-off-by: Werner Fink static void atexit_clear_unix_cache(); static dev_t find_net_dev(void); static void scan_procs(struct names *names_head, struct inode_list *ino_head, -@@ -109,9 +111,15 @@ static void debug_match_lists(struct nam +@@ -109,9 +113,12 @@ static void debug_match_lists(struct nam struct device_list *dev_head); #endif @@ -103,15 +102,12 @@ Signed-off-by: Werner Fink static void clear_mntinfo(void) __attribute__ ((__destructor__)); static void init_mntinfo(void) __attribute__ ((__constructor__)); +static int get_fdinfo(const pid_t pid, const char *fd, struct fdinfo *info); -+#if defined(HAS_NAME_TO_HANDLE_AT) -+static int get_mountid(const char *path); -+#endif +static int find_mountpoint(const char *path, mntinfo_t **mountinfo); +#if defined(WITH_MOUNTINFO_LIST) static int mntstat(const char *path, struct stat *buf); #endif static stat_t thestat = stat; -@@ -202,6 +210,7 @@ scan_procs(struct names *names_head, str +@@ -202,6 +209,7 @@ scan_procs(struct names *names_head, str struct stat *cwd_stat = NULL; struct stat *exe_stat = NULL; struct stat *root_stat = NULL; @@ -119,7 +115,7 @@ Signed-off-by: Werner Fink if (topproc_dent->d_name[0] < '0' || topproc_dent->d_name[0] > '9') /* Not a process */ continue; -@@ -211,9 +220,9 @@ scan_procs(struct names *names_head, str +@@ -211,9 +219,9 @@ scan_procs(struct names *names_head, str continue; uid = getpiduid(pid); @@ -132,7 +128,7 @@ Signed-off-by: Werner Fink cwd_dev = cwd_stat ? cwd_stat->st_dev : 0; exe_dev = exe_stat ? exe_stat->st_dev : 0; root_dev = root_stat ? root_stat->st_dev : 0; -@@ -221,39 +230,51 @@ scan_procs(struct names *names_head, str +@@ -221,21 +229,33 @@ scan_procs(struct names *names_head, str /* Scan the devices */ for (dev_tmp = dev_head; dev_tmp != NULL; dev_tmp = dev_tmp->next) { @@ -169,37 +165,32 @@ Signed-off-by: Werner Fink } for (ino_tmp = ino_head; ino_tmp != NULL; ino_tmp = ino_tmp->next) { -- if (exe_dev == ino_tmp->device) { -+ if (exe_dev == ino_tmp->device && ino_tmp->mnt_id == exe_id) { + if (exe_dev == ino_tmp->device) { if (!exe_stat) - exe_stat = get_pidstat(pid, "exe"); + exe_stat = get_pidstat(pid, "exe", NULL); if (exe_stat && exe_stat->st_dev == ino_tmp->device && exe_stat->st_ino == ino_tmp->inode) - add_matched_proc(ino_tmp->name, pid, - uid, ACCESS_EXE); +@@ -244,7 +264,7 @@ scan_procs(struct names *names_head, str } -- if (root_dev == ino_tmp->device) { -+ if (root_dev == ino_tmp->device && ino_tmp->mnt_id == root_id) { + if (root_dev == ino_tmp->device) { if (!root_stat) - root_stat = get_pidstat(pid, "root"); + root_stat = get_pidstat(pid, "root", NULL); if (root_stat && root_stat->st_dev == ino_tmp->device && root_stat->st_ino == ino_tmp->inode) - add_matched_proc(ino_tmp->name, pid, - uid, ACCESS_ROOT); +@@ -253,7 +273,7 @@ scan_procs(struct names *names_head, str } -- if (cwd_dev == ino_tmp->device) { -+ if (cwd_dev == ino_tmp->device && ino_tmp->mnt_id == cwd_id) { + if (cwd_dev == ino_tmp->device) { if (!cwd_stat) - cwd_stat = get_pidstat(pid, "cwd"); + cwd_stat = get_pidstat(pid, "cwd", NULL); if (cwd_stat && cwd_stat->st_dev == ino_tmp->device && cwd_stat->st_ino == ino_tmp->inode) -@@ -294,18 +315,42 @@ add_inode(struct inode_list **ino_list, +@@ -294,18 +314,42 @@ add_inode(struct inode_list **ino_list, ino_tmp->name = this_name; ino_tmp->device = device; ino_tmp->inode = inode; @@ -243,7 +234,7 @@ Signed-off-by: Werner Fink if ((dev_tmp = (struct device_list *)malloc(sizeof(struct device_list))) == NULL) -@@ -313,6 +358,10 @@ add_device(struct device_list **dev_list +@@ -313,6 +357,10 @@ add_device(struct device_list **dev_list dev_head = *dev_list; dev_tmp->name = this_name; dev_tmp->device = device; @@ -254,7 +245,7 @@ Signed-off-by: Werner Fink dev_tmp->next = dev_head; *dev_list = dev_tmp; } -@@ -454,13 +503,15 @@ add_special_proc(struct names *name_list +@@ -454,13 +502,15 @@ add_special_proc(struct names *name_list int parse_file(struct names *this_name, struct inode_list **ino_list, const opt_type opts) { @@ -271,7 +262,7 @@ Signed-off-by: Werner Fink if (errno == ENOENT) fprintf(stderr, _("Specified filename %s does not exist.\n"), -@@ -470,10 +521,12 @@ int parse_file(struct names *this_name, +@@ -470,10 +520,12 @@ int parse_file(struct names *this_name, this_name->filename, strerror(errno)); return -1; } @@ -286,10 +277,11 @@ Signed-off-by: Werner Fink #endif /* DEBUG */ add_inode(ino_list, this_name, this_name->st.st_dev, this_name->st.st_ino); -@@ -505,12 +558,43 @@ parse_mounts(struct names *this_name, st +@@ -505,12 +557,45 @@ parse_mounts(struct names *this_name, st const opt_type opts) { dev_t match_device; ++ mntinfo_t *mountinfo = NULL; + list_t *ptr; + int count; @@ -302,10 +294,8 @@ Signed-off-by: Werner Fink + count = 0; + list_for_each(ptr, &mntinfo) { + mntinfo_t *mnt = list_entry(ptr, mntinfo_t); -+ if (match_device != mnt->dev) -+ continue; + if (S_ISBLK(this_name->st.st_mode)) { -+ /* Correct mount IDs check if a block device ++ /* Skip mount IDs check if a block device + * was specified */ + this_name->mnt_id = mnt->id; + add_device(dev_list, this_name, match_device, mnt->dev); @@ -316,6 +306,8 @@ Signed-off-by: Werner Fink + } + if (this_name->mnt_id != mnt->id) + continue; ++ if (!mountinfo) ++ mountinfo = mnt; + count++; + } + if (count == 0) { @@ -327,11 +319,12 @@ Signed-off-by: Werner Fink + } + if (S_ISBLK(this_name->st.st_mode)) + return 0; ++ this_name->mnt_id = mountinfo->id; + add_device(dev_list, this_name, match_device, match_device); return 0; } -@@ -687,10 +771,12 @@ int parse_inet(struct names *this_name, +@@ -687,10 +772,12 @@ int parse_inet(struct names *this_name, break; #endif } @@ -347,7 +340,7 @@ Signed-off-by: Werner Fink } return 1; } -@@ -957,6 +1043,21 @@ free_inodes(struct inode_list **match_in +@@ -957,6 +1044,21 @@ free_inodes(struct inode_list **match_in /* * Free up structures allocated in add_device */ @@ -369,7 +362,7 @@ Signed-off-by: Werner Fink static void free_devices(struct device_list **match_devices) { -@@ -964,6 +1065,8 @@ free_devices(struct device_list **match_ +@@ -964,6 +1066,8 @@ free_devices(struct device_list **match_ device_tmp = *match_devices; while(device_tmp != NULL) { @@ -378,7 +371,7 @@ Signed-off-by: Werner Fink device_next = device_tmp->next; free(device_tmp); device_tmp = device_next; -@@ -1166,16 +1269,11 @@ int main(int argc, char *argv[]) +@@ -1166,16 +1270,11 @@ int main(int argc, char *argv[]) skip_argv = 1; //while(option != '\0') option++; if (strcmp(argv[argc_cnt], "tcp") == 0) @@ -400,7 +393,7 @@ Signed-off-by: Werner Fink else usage(_ ("Invalid namespace name")); -@@ -1215,7 +1313,7 @@ int main(int argc, char *argv[]) +@@ -1215,7 +1314,7 @@ int main(int argc, char *argv[]) } #if defined(WITH_MOUNTINFO_LIST) @@ -409,7 +402,7 @@ Signed-off-by: Werner Fink thestat = mntstat; #endif /* an option */ -@@ -1529,7 +1627,7 @@ print_matches(struct names *names_head, +@@ -1529,7 +1628,7 @@ print_matches(struct names *names_head, } @@ -418,7 +411,7 @@ Signed-off-by: Werner Fink { char pathname[256]; struct stat *st; -@@ -1541,6 +1639,15 @@ static struct stat *get_pidstat(const pi +@@ -1541,6 +1640,15 @@ static struct stat *get_pidstat(const pi free(st); return NULL; } @@ -434,41 +427,26 @@ Signed-off-by: Werner Fink return st; } -@@ -1555,7 +1662,7 @@ check_dir(const pid_t pid, const char *d +@@ -1555,7 +1663,8 @@ check_dir(const pid_t pid, const char *d struct inode_list *ino_tmp; struct device_list *dev_tmp; struct unixsocket_list *sock_tmp; - struct stat st, lst; ++ struct fdinfo fd; + struct stat st; char *dirpath; char filepath[PATH_MAX]; -@@ -1580,6 +1687,9 @@ check_dir(const pid_t pid, const char *d - filepath, strerror(errno)); +@@ -1594,11 +1703,34 @@ check_dir(const pid_t pid, const char *d } - } else { -+ struct fdinfo fd; -+ int fdret; -+ - thedev = st.st_dev; - if (thedev == netdev) { - for (sock_tmp = sockets; sock_tmp != NULL; -@@ -1592,13 +1702,37 @@ check_dir(const pid_t pid, const char *d - } - } - } -+ -+ memset(&fd, 0, sizeof(struct fdinfo)); -+ fdret = get_fdinfo(pid, direntry->d_name, &fd); -+ for (dev_tmp = dev_head; dev_tmp != NULL; dev_tmp = dev_tmp->next) { - if (thedev != dev_tmp->device) ++ int subvol_found = 0; + + if (thedev != dev_tmp->device) { + struct subvol *vol_tmp; -+ int subvol_found = 0; -+ ++ + for (vol_tmp = dev_tmp->vol; vol_tmp != NULL; + vol_tmp = vol_tmp->next) { + /* Check for BtrFS sub volumes as well */ @@ -477,14 +455,17 @@ Signed-off-by: Werner Fink + break; + } + } -+ ++ + if (!subvol_found) + continue; + } + -+ if (fdret != 0) ++ if (get_fdinfo(pid, direntry->d_name, &fd) != 0) + continue; -+ if (fd.mnt_id != dev_tmp->mnt_id) ++ ++ if (subvol_found && fd.mnt_id != dev_tmp->mnt_id) ++ continue; ++ else if (thedev != dev_tmp->device) continue; + if (access == ACCESS_FILE @@ -494,11 +475,11 @@ Signed-off-by: Werner Fink add_matched_proc(dev_tmp->name, pid, uid, ACCESS_FILEWR | -@@ -1620,9 +1754,10 @@ check_dir(const pid_t pid, const char *d +@@ -1620,9 +1752,10 @@ check_dir(const pid_t pid, const char *d continue; } if (st.st_ino == ino_tmp->inode) { -+ if (fdret != 0) ++ if (get_fdinfo(pid, direntry->d_name, &fd) != 0) + continue; if (access == ACCESS_FILE - && (lstat(filepath, &lst) == 0) @@ -507,7 +488,7 @@ Signed-off-by: Werner Fink add_matched_proc(ino_tmp->name, pid, uid, ACCESS_FILEWR | -@@ -1651,31 +1786,54 @@ check_map(const pid_t pid, const char *f +@@ -1651,31 +1784,54 @@ check_map(const pid_t pid, const char *f FILE *fp; unsigned long long tmp_inode; unsigned int tmp_maj, tmp_min; @@ -572,7 +553,7 @@ Signed-off-by: Werner Fink } fclose(fp); } -@@ -1699,6 +1857,7 @@ static uid_t getpiduid(const pid_t pid) +@@ -1699,6 +1855,7 @@ static uid_t getpiduid(const pid_t pid) * fill_unix_cache : Create a list of Unix sockets * This list is used later for matching purposes */ @@ -580,7 +561,7 @@ Signed-off-by: Werner Fink void fill_unix_cache(struct unixsocket_list **unixsocket_head) { FILE *fp; -@@ -1715,6 +1874,8 @@ void fill_unix_cache(struct unixsocket_l +@@ -1715,6 +1872,8 @@ void fill_unix_cache(struct unixsocket_l while (fgets(line, BUFSIZ, fp) != NULL) { char *path; char *scanned_path = NULL; @@ -589,7 +570,7 @@ Signed-off-by: Werner Fink if (sscanf(line, "%*x: %*x %*x %*x %*x %*d %llu %ms", &scanned_inode, &scanned_path) != 2) { if (scanned_path) -@@ -1730,6 +1891,8 @@ void fill_unix_cache(struct unixsocket_l +@@ -1730,6 +1889,8 @@ void fill_unix_cache(struct unixsocket_l free(path); continue; } @@ -598,7 +579,7 @@ Signed-off-by: Werner Fink if ((newsocket = (struct unixsocket_list *) malloc(sizeof(struct unixsocket_list))) == NULL) { free(path); -@@ -1738,6 +1901,7 @@ void fill_unix_cache(struct unixsocket_l +@@ -1738,6 +1899,7 @@ void fill_unix_cache(struct unixsocket_l newsocket->sun_name = strdup(scanned_path); newsocket->inode = st.st_ino; newsocket->dev = st.st_dev; @@ -606,7 +587,7 @@ Signed-off-by: Werner Fink newsocket->net_inode = scanned_inode; newsocket->next = *unixsocket_head; *unixsocket_head = newsocket; -@@ -1750,6 +1914,7 @@ void fill_unix_cache(struct unixsocket_l +@@ -1750,6 +1912,7 @@ void fill_unix_cache(struct unixsocket_l /* * Free up the list of Unix sockets */ @@ -614,7 +595,7 @@ Signed-off-by: Werner Fink void clear_unix_cache(struct unixsocket_list **unixsocket_head) { while(*unixsocket_head != NULL) { -@@ -1921,34 +2086,21 @@ scan_mounts(struct names *names_head, st +@@ -1921,34 +2084,21 @@ scan_mounts(struct names *names_head, st { struct device_list *dev_tmp; struct inode_list *ino_tmp; @@ -657,7 +638,7 @@ Signed-off-by: Werner Fink add_special_proc(dev_tmp->name, PTYPE_MOUNT, 0, find_mountp); } -@@ -1960,7 +2112,6 @@ scan_mounts(struct names *names_head, st +@@ -1960,7 +2110,6 @@ scan_mounts(struct names *names_head, st find_mountp); } } @@ -665,7 +646,7 @@ Signed-off-by: Werner Fink } static void -@@ -2013,16 +2164,44 @@ scan_swaps(struct names *names_head, str +@@ -2013,16 +2162,44 @@ scan_swaps(struct names *names_head, str fclose(fp); } @@ -714,7 +695,7 @@ Signed-off-by: Werner Fink { list_t *ptr, *tmp; -@@ -2033,72 +2212,276 @@ static void clear_mntinfo(void) +@@ -2033,72 +2210,247 @@ static void clear_mntinfo(void) } } @@ -738,11 +719,6 @@ Signed-off-by: Werner Fink return; - if ((mnt = fopen("/proc/self/mountinfo", "r")) == (FILE *) 0) +#if defined(HAS_MOUNTINFO) -+ /* -+ * We could also loop over all mount namespaces, that is not only -+ * over /proc/self/ns/mnt. But this expands this list as well as -+ * we can use name_to_handle_at(2) in our get_mountid() function. -+ */ + if ((mnt = fopen(PROC_MOUNTINFO, "r")) == (FILE *) 0) return; while (fscanf @@ -758,6 +734,16 @@ Signed-off-by: Werner Fink - ("Cannot allocate memory for matched proc: %s\n"), - strerror(errno)); - exit(1); +- } +- append(mnt, mntinfo); +- mnt->mpoint = ((char *)mnt) + alignof(mntinfo_t); +- strcpy(mnt->mpoint, mpoint); +- mnt->nlen = nlen; +- mnt->parid = parid; +- mnt->dev = makedev(maj, min); +- mnt->id = mid; +- if (mid > max) +- max = mid; + (mnt, "%i %i %u:%u %*s %s %*[^-] - %s %s %*[^\n]", + &mid, &parid, &maj, &min, &mpoint[0], &type[0], &devname[0]) == 7) { + struct stat st; @@ -768,16 +754,7 @@ Signed-off-by: Werner Fink + stat(mpoint, &st); + mntinf->dev = st.st_dev; /* stat(2) on binary does not see subvol dev */ + } - } -- append(mnt, mntinfo); -- mnt->mpoint = ((char *)mnt) + alignof(mntinfo_t); -- strcpy(mnt->mpoint, mpoint); -- mnt->nlen = nlen; -- mnt->parid = parid; -- mnt->dev = makedev(maj, min); -- mnt->id = mid; -- if (mid > max) -- max = mid; ++ } } +#else + if ((mnt = fopen(PROC_MOUNTS, "r")) == (FILE *) 0) @@ -803,48 +780,41 @@ Signed-off-by: Werner Fink +#endif fclose(mnt); +} -+ + +- /* Sort mount points accordingly to the reverse mount order */ +- initial(&sort); +- for (mid = 1; mid <= max; mid++) { +- list_t *ptr, *tmp; +- list_for_each_safe(ptr, tmp, &mntinfo) { +static int +get_fdinfo(const pid_t pid, const char *fd, struct fdinfo *info) +{ + int ret = 0; + char pathname[256]; + int mnt_id = 0, flags = 0; -+#if defined(HAS_FDINFO) /* Here we get the private namespace as well */ ++#if defined(HAS_FDINFO) + const static char delimiters[] = ": \t\n"; + char line[BUFSIZ]; + FILE *fp; -+# if defined(HAS_NAME_TO_HANDLE_AT) -+ static ino_t mynamespace; -+ struct stat st; -+ -+ if (!mynamespace) { -+ if (stat("/proc/self/ns/mnt", &st) != 0) { -+ fprintf(stderr, _("Cannot stat %s: %s\n"), -+ "/proc/self/ns/mnt", strerror(errno)); -+ exit(1); -+ } -+ mynamespace = st.st_ino; -+ } -+# endif ++ + snprintf(pathname, 256, "/proc/%d/fdinfo/%s", pid, fd); + if ((fp = fopen(pathname, "r")) == NULL) -+ goto out; /* forbidden namesspace, try our own namespace */ ++ goto out; + while (fgets(line, BUFSIZ, fp) && ret < 2) { -+ char *xp, *vp, *ep; ++ char *fp, *vp, *ep; + unsigned long ul; -+ xp = strtok(&line[0], delimiters); -+ if (!xp || *xp == 0) ++ fp = strtok(&line[0], delimiters); ++ if (!fp || *fp == 0) + continue; + vp = strtok(NULL, delimiters); + if (!vp || *vp == 0) + continue; -+ if (strcmp(xp, "flags") == 0 && (ul = strtoul(vp, &ep, 0)) != ULONG_MAX && ep && *ep == 0) { ++ if (strcmp(fp, "flags") == 0 && (ul = strtoul(vp, &ep, 0)) != ULONG_MAX && ep && *ep == 0) { + info->flags = (mode_t)ul; + flags++; + ret++; + } -+ if (strcmp(xp, "mnt_id") == 0 && (ul = strtoul(vp, &ep, 0)) != ULONG_MAX && ep && *ep == 0) { ++ if (strcmp(fp, "mnt_id") == 0 && (ul = strtoul(vp, &ep, 0)) != ULONG_MAX && ep && *ep == 0) { + info->mnt_id = (int)ul; + mnt_id++; + ret++; @@ -852,18 +822,6 @@ Signed-off-by: Werner Fink + } + fclose(fp); +out: -+# if defined(HAS_NAME_TO_HANDLE_AT) -+ snprintf(pathname, 256, "/proc/%d/ns/mnt", pid); -+ if (stat(pathname, &st) == 0 && mynamespace != st.st_ino) { -+ char *realname; -+ snprintf(pathname, 256, "/proc/%d/fd/%s", pid, fd); -+ realname = expandpath(pathname); -+ if (realname) { /* Use our namespace for mount ID */ -+ info->mnt_id = get_mountid(realname); -+ mnt_id++; -+ } -+ } -+# endif +#endif + if (!flags || !mnt_id) { + struct stat lst; @@ -888,12 +846,7 @@ Signed-off-by: Werner Fink + } + return ret == 2 ? 0 : -1; +} - -- /* Sort mount points accordingly to the reverse mount order */ -- initial(&sort); -- for (mid = 1; mid <= max; mid++) { -- list_t *ptr, *tmp; -- list_for_each_safe(ptr, tmp, &mntinfo) { ++ +#if defined(HAS_NAME_TO_HANDLE_AT) +static int +get_mountid(const char *path) @@ -1035,7 +988,7 @@ Signed-off-by: Werner Fink /* * Determine device of links below /proc/ */ -@@ -2106,8 +2489,7 @@ static int mntstat(const char *path, str +@@ -2106,8 +2458,7 @@ static int mntstat(const char *path, str { char name[PATH_MAX + 1]; const char *use; @@ -1045,7 +998,7 @@ Signed-off-by: Werner Fink if ((use = realpath(path, name)) == NULL || *use != '/') { -@@ -2119,27 +2501,26 @@ static int mntstat(const char *path, str +@@ -2119,27 +2470,26 @@ static int mntstat(const char *path, str errno = 0; return stat(path, buf); } @@ -1092,7 +1045,7 @@ Signed-off-by: Werner Fink #endif /* WITH_MOUNTINFO_LIST */ --- src/fuser.h -+++ src/fuser.h 2021-05-07 15:01:31.954757006 +0000 ++++ src/fuser.h 2021-03-05 13:57:45.215585084 +0000 @@ -37,10 +37,16 @@ struct procs { #define PTYPE_KNFSD 2 #define PTYPE_SWAP 3 @@ -1171,7 +1124,7 @@ Signed-off-by: Werner Fink #define PROC_MOUNTS "/proc/mounts" #define PROC_SWAPS "/proc/swaps" --- src/timeout.c -+++ src/timeout.c 2021-05-07 15:01:31.954757006 +0000 ++++ src/timeout.c 2021-03-05 13:57:45.215585084 +0000 @@ -67,9 +67,6 @@ # ifndef constructor # define constructor __constructor__ diff --git a/0002-Use-new-statx-2-system-call-to-avoid-hangs-on-NFS.patch b/0002-Use-new-statx-2-system-call-to-avoid-hangs-on-NFS.patch index e80c5a9..d3c9eb1 100644 --- a/0002-Use-new-statx-2-system-call-to-avoid-hangs-on-NFS.patch +++ b/0002-Use-new-statx-2-system-call-to-avoid-hangs-on-NFS.patch @@ -1,19 +1,19 @@ -From f2ada8ea7939bc8f607d88a10c92d5bb96a700b8 Mon Sep 17 00:00:00 2001 +From 9f3910df62bcc1f726b8e84f9ffc40c4d7916eac Mon Sep 17 00:00:00 2001 From: Werner Fink -Date: Fri, 7 May 2021 16:36:28 +0200 +Date: Thu, 14 Jan 2021 11:37:46 +0100 Subject: [PATCH] Use new statx(2) system call to avoid hangs on NFS Signed-off-by: Werner Fink --- Makefile.am | 4 - - configure.ac | 24 +++++---- - src/fuser.c | 102 ++++++++++------------------------------ + configure.ac | 38 +++++---------- + src/fuser.c | 98 +++++++++----------------------------- src/statx.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/statx.h | 68 ++++++++++++++++++++++++++ - 5 files changed, 260 insertions(+), 87 deletions(-) + 5 files changed, 258 insertions(+), 99 deletions(-) --- Makefile.am -+++ Makefile.am 2021-05-07 15:04:28.611513529 +0000 ++++ Makefile.am 2021-01-14 11:29:22.011223930 +0000 @@ -64,8 +64,8 @@ src_fuser_SOURCES = \ src/fuser.h \ src/lists.h @@ -26,8 +26,29 @@ Signed-off-by: Werner Fink src_fuser_LDADD = @LIBINTL@ src_killall_SOURCES = src/killall.c src/comm.h src/signals.c src/signals.h src/i18n.h --- configure.ac -+++ configure.ac 2021-05-07 15:04:28.623513310 +0000 -@@ -57,16 +57,20 @@ fi ++++ configure.ac 2021-01-14 11:29:22.011223930 +0000 +@@ -30,20 +30,6 @@ if test "$enable_selinux" = "yes"; then + fi + AC_SUBST([SELINUX_LIB]) + +-# Call fork before all stat calls to stop hanging on NFS mounts +-AC_SUBST([WITH_TIMEOUT_STAT]) +-AC_ARG_ENABLE([timeout_stat], +- [AS_HELP_STRING([--enable-timeout-stat], [Use a timeout on stat calls (optional with argument "static" for a static background process)])], +- [enable_timeout_stat=$enableval], +- [enable_timeout_stat="no"]) +-if test "$enable_timeout_stat" = "yes"; then +- AC_DEFINE([WITH_TIMEOUT_STAT], [1], [Use timeout on stat calls]) +-fi +-if test "$enable_timeout_stat" = "static"; then +- AC_DEFINE([WITH_TIMEOUT_STAT], [2], [Use timeout on stat calls]) +-fi +-AM_CONDITIONAL([WANT_TIMEOUT_STAT], [test "$enable_timeout_stat" = "static"]) +- + # Use /proc/self/mountinfo if available + if test -e /proc/self/mountinfo ; then + AC_DEFINE([HAS_MOUNTINFO], [1], [System has /proc/self/mountinfo which can used instead /proc(/self)/mounts]) +@@ -57,16 +43,20 @@ fi AC_CHECK_FUNC([name_to_handle_at],[ AC_DEFINE([HAS_NAME_TO_HANDLE_AT], [1], [System has name_to_handle_at(2) system call])]) @@ -59,8 +80,8 @@ Signed-off-by: Werner Fink # Enable hardened compile and link flags AC_ARG_ENABLE([harden_flags], --- src/fuser.c -+++ src/fuser.c 2021-05-07 15:04:28.627513237 +0000 -@@ -61,7 +61,7 @@ ++++ src/fuser.c 2021-01-14 11:30:10.750278604 +0000 +@@ -63,7 +63,7 @@ #include "fuser.h" #include "signals.h" #include "i18n.h" @@ -69,9 +90,9 @@ Signed-off-by: Werner Fink #include "comm.h" //#define DEBUG 1 -@@ -119,10 +119,6 @@ static int get_fdinfo(const pid_t pid, c - static int get_mountid(const char *path); - #endif +@@ -118,10 +118,6 @@ static void clear_mntinfo(void) __attrib + static void init_mntinfo(void) __attribute__ ((__constructor__)); + static int get_fdinfo(const pid_t pid, const char *fd, struct fdinfo *info); static int find_mountpoint(const char *path, mntinfo_t **mountinfo); -#if defined(WITH_MOUNTINFO_LIST) -static int mntstat(const char *path, struct stat *buf); @@ -80,7 +101,7 @@ Signed-off-by: Werner Fink static char *expandpath(const char *path); static struct unixsocket_list *unixsockets = NULL; static struct names *names_head = NULL, *names_tail = NULL; -@@ -510,7 +506,7 @@ int parse_file(struct names *this_name, +@@ -509,7 +505,7 @@ int parse_file(struct names *this_name, free(this_name->filename); this_name->filename = strdup(new); } @@ -89,7 +110,7 @@ Signed-off-by: Werner Fink find_mountpoint(this_name->filename, &mountinfo) != 0) { if (errno == ENOENT) fprintf(stderr, -@@ -1244,9 +1240,7 @@ int main(int argc, char *argv[]) +@@ -1245,9 +1241,7 @@ int main(int argc, char *argv[]) opts |= OPT_INTERACTIVE; break; case 'I': @@ -99,7 +120,7 @@ Signed-off-by: Werner Fink break; case 'k': opts |= OPT_KILL; -@@ -1312,10 +1306,11 @@ int main(int argc, char *argv[]) +@@ -1313,10 +1307,11 @@ int main(int argc, char *argv[]) continue; } @@ -114,7 +135,7 @@ Signed-off-by: Werner Fink /* an option */ /* Not an option, must be a file specification */ if ((this_name = malloc(sizeof(struct names))) == NULL) -@@ -1635,7 +1630,7 @@ static struct stat *get_pidstat(const pi +@@ -1636,7 +1631,7 @@ static struct stat *get_pidstat(const pi if ((st = (struct stat *)malloc(sizeof(struct stat))) == NULL) return NULL; snprintf(pathname, 256, "/proc/%d/%s", pid, filename); @@ -123,7 +144,7 @@ Signed-off-by: Werner Fink free(st); return NULL; } -@@ -1681,7 +1676,7 @@ check_dir(const pid_t pid, const char *d +@@ -1683,7 +1678,7 @@ check_dir(const pid_t pid, const char *d snprintf(filepath, sizeof filepath - 1, "/proc/%d/%s/%s", pid, dirname, direntry->d_name); @@ -132,7 +153,7 @@ Signed-off-by: Werner Fink if (errno != ENOENT && errno != ENOTDIR) { fprintf(stderr, _("Cannot stat file %s: %s\n"), filepath, strerror(errno)); -@@ -1747,7 +1742,7 @@ check_dir(const pid_t pid, const char *d +@@ -1740,7 +1735,7 @@ check_dir(const pid_t pid, const char *d if (thedev != ino_tmp->device) continue; if (!st.st_ino @@ -141,7 +162,7 @@ Signed-off-by: Werner Fink fprintf(stderr, _("Cannot stat file %s: %s\n"), filepath, strerror(errno)); -@@ -1845,11 +1840,11 @@ static uid_t getpiduid(const pid_t pid) +@@ -1838,11 +1833,11 @@ static uid_t getpiduid(const pid_t pid) if (asprintf(&pathname, "/proc/%d", pid) < 0) return 0; @@ -157,7 +178,7 @@ Signed-off-by: Werner Fink return st.st_uid; } -@@ -1887,7 +1882,7 @@ void fill_unix_cache(struct unixsocket_l +@@ -1880,7 +1875,7 @@ void fill_unix_cache(struct unixsocket_l path = scanned_path; if (*scanned_path == '@') scanned_path++; @@ -166,7 +187,7 @@ Signed-off-by: Werner Fink free(path); continue; } -@@ -2022,7 +2017,7 @@ static dev_t find_net_dev(void) +@@ -2015,7 +2010,7 @@ static dev_t find_net_dev(void) fprintf(stderr, _("Cannot open a network socket.\n")); return -1; } @@ -175,7 +196,7 @@ Signed-off-by: Werner Fink fprintf(stderr, _("Cannot find socket's device number.\n")); close(skt); return -1; -@@ -2059,7 +2054,7 @@ scan_knfsd(struct names *names_head, str +@@ -2052,7 +2047,7 @@ scan_knfsd(struct names *names_head, str if ((find_space = strpbrk(line, " \t")) == NULL) continue; *find_space = '\0'; @@ -184,7 +205,7 @@ Signed-off-by: Werner Fink continue; } /* Scan the devices */ -@@ -2093,7 +2088,7 @@ scan_mounts(struct names *names_head, st +@@ -2086,7 +2081,7 @@ scan_mounts(struct names *names_head, st mntinfo_t *mnt = list_entry(ptr, mntinfo_t); const char *find_mountp = mnt->mpoint; @@ -193,7 +214,7 @@ Signed-off-by: Werner Fink continue; /* Scan the devices */ -@@ -2143,7 +2138,7 @@ scan_swaps(struct names *names_head, str +@@ -2136,7 +2131,7 @@ scan_swaps(struct names *names_head, str if (*find_space == '\0') continue; } @@ -202,7 +223,7 @@ Signed-off-by: Werner Fink continue; } /* Scan the devices */ -@@ -2240,10 +2235,10 @@ init_mntinfo(void) +@@ -2228,10 +2223,10 @@ init_mntinfo(void) &mid, &parid, &maj, &min, &mpoint[0], &type[0], &devname[0]) == 7) { struct stat st; mntinf = add_mntinfo(mpoint, type, mid, parid, makedev(maj, min)); @@ -215,7 +236,7 @@ Signed-off-by: Werner Fink mntinf->dev = st.st_dev; /* stat(2) on binary does not see subvol dev */ } } -@@ -2255,7 +2250,7 @@ init_mntinfo(void) +@@ -2243,7 +2238,7 @@ init_mntinfo(void) parid = -1; while (fscanf (mnt, "%s %s %s %*[^\n]", &devname[0], &mpoint[0], &type[0]) == 3) { struct stat st; @@ -224,7 +245,7 @@ Signed-off-by: Werner Fink if (errno != EACCES) { fprintf(stderr, _("Cannot stat %s: %s\n"), mpoint, strerror(errno)); -@@ -2264,7 +2259,7 @@ init_mntinfo(void) +@@ -2252,7 +2247,7 @@ init_mntinfo(void) st.st_dev = (dev_t)-1; } mntinf = add_mntinfo(mpoint, type, mid++, parid, st.st_dev); @@ -233,25 +254,7 @@ Signed-off-by: Werner Fink if (st.st_rdev != 0 && mntinf->dev != st.st_rdev) mntinf->vol = st.st_rdev; } -@@ -2288,7 +2283,7 @@ get_fdinfo(const pid_t pid, const char * - struct stat st; - - if (!mynamespace) { -- if (stat("/proc/self/ns/mnt", &st) != 0) { -+ if (statn("/proc/self/ns/mnt", STATX_INO, &st) != 0) { - fprintf(stderr, _("Cannot stat %s: %s\n"), - "/proc/self/ns/mnt", strerror(errno)); - exit(1); -@@ -2323,7 +2318,7 @@ get_fdinfo(const pid_t pid, const char * - out: - # if defined(HAS_NAME_TO_HANDLE_AT) - snprintf(pathname, 256, "/proc/%d/ns/mnt", pid); -- if (stat(pathname, &st) == 0 && mynamespace != st.st_ino) { -+ if (statn(pathname, STATX_INO, &st) == 0 && mynamespace != st.st_ino) { - char *realname; - snprintf(pathname, 256, "/proc/%d/fd/%s", pid, fd); - realname = expandpath(pathname); -@@ -2338,7 +2333,7 @@ out: +@@ -2302,7 +2297,7 @@ out: struct stat lst; snprintf(pathname, 256, "/proc/%d/fd/%s", pid, fd); @@ -260,7 +263,7 @@ Signed-off-by: Werner Fink if (lst.st_mode & S_IWUSR) info->flags |= O_WRONLY; ret++; -@@ -2411,7 +2406,7 @@ find_mountpoint(const char *path, mntinf +@@ -2375,7 +2370,7 @@ find_mountpoint(const char *path, mntinf /* could be a chroot or a container */ @@ -269,7 +272,7 @@ Signed-off-by: Werner Fink if (errno != EACCES) { fprintf(stderr, _("Cannot stat %s: %s\n"), path, strerror(errno)); -@@ -2443,7 +2438,7 @@ find_mountpoint(const char *path, mntinf +@@ -2407,7 +2402,7 @@ find_mountpoint(const char *path, mntinf /* could be a chroot or a container */ @@ -278,7 +281,7 @@ Signed-off-by: Werner Fink if (errno != EACCES) { fprintf(stderr, _("Cannot stat %s: %s\n"), use, strerror(errno)); -@@ -2481,49 +2476,6 @@ out: +@@ -2445,49 +2440,6 @@ out: return ret; } @@ -329,7 +332,7 @@ Signed-off-by: Werner Fink * Somehow the realpath(3) glibc function call, nevertheless * it avoids lstat(2) system calls. --- src/statx.c -+++ src/statx.c 2021-05-07 15:04:28.627513237 +0000 ++++ src/statx.c 2021-01-14 11:29:22.015223853 +0000 @@ -0,0 +1,149 @@ +/* + * statx.c - Map modern statx(2) system call to older stat(2), lstat(2), @@ -481,7 +484,7 @@ Signed-off-by: Werner Fink + return ret; +} --- src/statx.h -+++ src/statx.h 2021-05-07 15:04:28.627513237 +0000 ++++ src/statx.h 2021-01-14 11:29:22.019223776 +0000 @@ -0,0 +1,68 @@ +/* + * statx.h - Map modern statx(2) system call to older stat(2), lstat(2), diff --git a/psmisc-v23.3.dif b/psmisc-v23.3.dif index bcf9772..aa80e2a 100644 --- a/psmisc-v23.3.dif +++ b/psmisc-v23.3.dif @@ -5,7 +5,7 @@ --- configure.ac +++ configure.ac 2021-01-14 11:31:31.640709812 +0000 -@@ -145,7 +145,7 @@ AC_CHECK_MEMBERS([struct user_regs_struc +@@ -129,7 +129,7 @@ AC_CHECK_MEMBERS([struct user_regs_struc struct user_regs_struct.rdi, struct user_regs_struct.rsi, struct user_regs_struct.rdx], [],[], @@ -16,7 +16,7 @@ struct pt_regs.gpr], [],[], [#include ]) --- src/fuser.c +++ src/fuser.c 2021-01-14 11:31:31.640709812 +0000 -@@ -1145,6 +1145,7 @@ int main(int argc, char *argv[]) +@@ -1146,6 +1146,7 @@ int main(int argc, char *argv[]) struct option *optr; char *nsptr; int skip_argv; @@ -24,7 +24,7 @@ struct option options[] = { {"all", 0, NULL, 'a'}, -@@ -1188,6 +1189,7 @@ int main(int argc, char *argv[]) +@@ -1189,6 +1190,7 @@ int main(int argc, char *argv[]) #endif atexit(atexit_free_lists); @@ -32,7 +32,7 @@ for (argc_cnt = 1; argc_cnt < argc; argc_cnt++) { current_argv = argv[argc_cnt]; if (current_argv[0] == '-') { /* its an option */ -@@ -1332,6 +1334,7 @@ int main(int argc, char *argv[]) +@@ -1333,6 +1335,7 @@ int main(int argc, char *argv[]) } } this_name->matched_procs = NULL; @@ -40,7 +40,7 @@ if (opts & (OPT_MOUNTS | OPT_ISMOUNTPOINT) && this_name->name_space != NAMESPACE_FILE) { free(this_name); -@@ -1385,7 +1388,7 @@ int main(int argc, char *argv[]) +@@ -1386,7 +1389,7 @@ int main(int argc, char *argv[]) names_tail->next = this_name; names_tail = this_name; } /* for across the argvs */ diff --git a/psmisc.changes b/psmisc.changes index 4443366..4f7e8ce 100644 --- a/psmisc.changes +++ b/psmisc.changes @@ -1,10 +1,3 @@ -------------------------------------------------------------------- -Fri May 7 14:53:08 UTC 2021 - Dr. Werner Fink - -- Change patch 0001-Use-mountinfo-to-be-able-to-use-the-mount-identity.patch - * Fix bsc#1185208 to make private mount namespaces work as well - as to distinguish NFS mounts from same remote device share. - ------------------------------------------------------------------- Fri Mar 5 14:10:11 UTC 2021 - Dr. Werner Fink diff --git a/psmisc.spec b/psmisc.spec index 3263ed3..fa6e13e 100644 --- a/psmisc.spec +++ b/psmisc.spec @@ -23,8 +23,6 @@ BuildRequires: dejagnu BuildRequires: gcc-c++ BuildRequires: gettext-devel BuildRequires: glibc-devel -BuildRequires: libcap-devel -BuildRequires: libcap-progs BuildRequires: libselinux-devel BuildRequires: linux-glibc-devel >= 4.12 BuildRequires: ncurses-devel @@ -96,16 +94,13 @@ rm -f %{buildroot}%{_mandir}/man1/peekfd.1* %endif %find_lang psmisc -%post -setcap cap_dac_read_search=ep %{_bindir}/fuser - %files %defattr (-,root,root,755) %license COPYING %if !0%{?usrmerged} /bin/fuser %endif -%verify(not mode caps) %{_bindir}/fuser +%{_bindir}/fuser %{_bindir}/killall %ifarch %have_peekfd %{_bindir}/peekfd