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 e734897..3b8c06e 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 e5d42c39541c94c00d97ed490add24bc898ebe0a Mon Sep 17 00:00:00 2001 +From bfa17afa43fc1b98c2bbc9c54416db9ccb505028 Mon Sep 17 00:00:00 2001 From: Werner Fink -Date: Wed, 13 Jan 2021 11:59:24 +0100 +Date: Fri, 7 May 2021 16:25:13 +0200 Subject: [PATCH] Use mountinfo to be able to use the mount identity which allows to distinguish different mounts with the @@ -19,16 +19,19 @@ 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 | 646 ++++++++++++++++++++++++++++++++++++++++++++-------------- + src/fuser.c | 681 +++++++++++++++++++++++++++++++++++++++++++++------------- src/fuser.h | 27 +- src/timeout.c | 5 - 4 files changed, 534 insertions(+), 159 deletions(-) + 4 files changed, 567 insertions(+), 161 deletions(-) --- configure.ac -+++ configure.ac 2021-03-05 13:57:45.175585808 +0000 ++++ configure.ac 2021-05-07 15:01:31.910757814 +0000 @@ -44,6 +44,19 @@ if test "$enable_timeout_stat" = "static fi AM_CONDITIONAL([WANT_TIMEOUT_STAT], [test "$enable_timeout_stat" = "static"]) @@ -59,19 +62,17 @@ Signed-off-by: Werner Fink dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST --- src/fuser.c -+++ src/fuser.c 2021-03-05 14:03:20.189518326 +0000 -@@ -32,6 +32,10 @@ ++++ src/fuser.c 2021-05-07 15:03:42.232365037 +0000 +@@ -32,6 +32,8 @@ #include #include #include +#include -+#if defined(HAS_GETFH) +#include -+#endif #include #include #include -@@ -79,7 +83,7 @@ static void check_map(const pid_t pid, c +@@ -79,7 +81,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); @@ -80,7 +81,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 +92,9 @@ static int kill_matched_proc(struct proc +@@ -88,9 +90,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, @@ -93,7 +94,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 +113,12 @@ static void debug_match_lists(struct nam +@@ -109,9 +111,15 @@ static void debug_match_lists(struct nam struct device_list *dev_head); #endif @@ -102,12 +103,15 @@ 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 +209,7 @@ scan_procs(struct names *names_head, str +@@ -202,6 +210,7 @@ scan_procs(struct names *names_head, str struct stat *cwd_stat = NULL; struct stat *exe_stat = NULL; struct stat *root_stat = NULL; @@ -115,7 +119,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 +219,9 @@ scan_procs(struct names *names_head, str +@@ -211,9 +220,9 @@ scan_procs(struct names *names_head, str continue; uid = getpiduid(pid); @@ -128,7 +132,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,21 +229,33 @@ scan_procs(struct names *names_head, str +@@ -221,39 +230,51 @@ scan_procs(struct names *names_head, str /* Scan the devices */ for (dev_tmp = dev_head; dev_tmp != NULL; dev_tmp = dev_tmp->next) { @@ -165,32 +169,37 @@ 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) { ++ if (exe_dev == ino_tmp->device && ino_tmp->mnt_id == exe_id) { 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) -@@ -244,7 +264,7 @@ scan_procs(struct names *names_head, str + add_matched_proc(ino_tmp->name, pid, + uid, ACCESS_EXE); } - if (root_dev == ino_tmp->device) { +- if (root_dev == ino_tmp->device) { ++ if (root_dev == ino_tmp->device && ino_tmp->mnt_id == root_id) { 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) -@@ -253,7 +273,7 @@ scan_procs(struct names *names_head, str + add_matched_proc(ino_tmp->name, pid, + uid, ACCESS_ROOT); } - if (cwd_dev == ino_tmp->device) { +- if (cwd_dev == ino_tmp->device) { ++ if (cwd_dev == ino_tmp->device && ino_tmp->mnt_id == cwd_id) { 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 +314,42 @@ add_inode(struct inode_list **ino_list, +@@ -294,18 +315,42 @@ add_inode(struct inode_list **ino_list, ino_tmp->name = this_name; ino_tmp->device = device; ino_tmp->inode = inode; @@ -234,7 +243,7 @@ Signed-off-by: Werner Fink if ((dev_tmp = (struct device_list *)malloc(sizeof(struct device_list))) == NULL) -@@ -313,6 +357,10 @@ add_device(struct device_list **dev_list +@@ -313,6 +358,10 @@ add_device(struct device_list **dev_list dev_head = *dev_list; dev_tmp->name = this_name; dev_tmp->device = device; @@ -245,7 +254,7 @@ Signed-off-by: Werner Fink dev_tmp->next = dev_head; *dev_list = dev_tmp; } -@@ -454,13 +502,15 @@ add_special_proc(struct names *name_list +@@ -454,13 +503,15 @@ add_special_proc(struct names *name_list int parse_file(struct names *this_name, struct inode_list **ino_list, const opt_type opts) { @@ -262,7 +271,7 @@ Signed-off-by: Werner Fink if (errno == ENOENT) fprintf(stderr, _("Specified filename %s does not exist.\n"), -@@ -470,10 +520,12 @@ int parse_file(struct names *this_name, +@@ -470,10 +521,12 @@ int parse_file(struct names *this_name, this_name->filename, strerror(errno)); return -1; } @@ -277,11 +286,10 @@ 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 +557,45 @@ parse_mounts(struct names *this_name, st +@@ -505,12 +558,43 @@ parse_mounts(struct names *this_name, st const opt_type opts) { dev_t match_device; -+ mntinfo_t *mountinfo = NULL; + list_t *ptr; + int count; @@ -294,8 +302,10 @@ 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)) { -+ /* Skip mount IDs check if a block device ++ /* Correct 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); @@ -306,8 +316,6 @@ Signed-off-by: Werner Fink + } + if (this_name->mnt_id != mnt->id) + continue; -+ if (!mountinfo) -+ mountinfo = mnt; + count++; + } + if (count == 0) { @@ -319,12 +327,11 @@ 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 +772,12 @@ int parse_inet(struct names *this_name, +@@ -687,10 +771,12 @@ int parse_inet(struct names *this_name, break; #endif } @@ -340,7 +347,7 @@ Signed-off-by: Werner Fink } return 1; } -@@ -957,6 +1044,21 @@ free_inodes(struct inode_list **match_in +@@ -957,6 +1043,21 @@ free_inodes(struct inode_list **match_in /* * Free up structures allocated in add_device */ @@ -362,7 +369,7 @@ Signed-off-by: Werner Fink static void free_devices(struct device_list **match_devices) { -@@ -964,6 +1066,8 @@ free_devices(struct device_list **match_ +@@ -964,6 +1065,8 @@ free_devices(struct device_list **match_ device_tmp = *match_devices; while(device_tmp != NULL) { @@ -371,7 +378,7 @@ Signed-off-by: Werner Fink device_next = device_tmp->next; free(device_tmp); device_tmp = device_next; -@@ -1166,16 +1270,11 @@ int main(int argc, char *argv[]) +@@ -1166,16 +1269,11 @@ int main(int argc, char *argv[]) skip_argv = 1; //while(option != '\0') option++; if (strcmp(argv[argc_cnt], "tcp") == 0) @@ -393,7 +400,7 @@ Signed-off-by: Werner Fink else usage(_ ("Invalid namespace name")); -@@ -1215,7 +1314,7 @@ int main(int argc, char *argv[]) +@@ -1215,7 +1313,7 @@ int main(int argc, char *argv[]) } #if defined(WITH_MOUNTINFO_LIST) @@ -402,7 +409,7 @@ Signed-off-by: Werner Fink thestat = mntstat; #endif /* an option */ -@@ -1529,7 +1628,7 @@ print_matches(struct names *names_head, +@@ -1529,7 +1627,7 @@ print_matches(struct names *names_head, } @@ -411,7 +418,7 @@ Signed-off-by: Werner Fink { char pathname[256]; struct stat *st; -@@ -1541,6 +1640,15 @@ static struct stat *get_pidstat(const pi +@@ -1541,6 +1639,15 @@ static struct stat *get_pidstat(const pi free(st); return NULL; } @@ -427,26 +434,41 @@ Signed-off-by: Werner Fink return st; } -@@ -1555,7 +1663,8 @@ check_dir(const pid_t pid, const char *d +@@ -1555,7 +1662,7 @@ 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]; -@@ -1594,11 +1703,34 @@ check_dir(const pid_t pid, const char *d +@@ -1580,6 +1687,9 @@ check_dir(const pid_t pid, const char *d + filepath, strerror(errno)); } + } 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 */ @@ -455,17 +477,14 @@ Signed-off-by: Werner Fink + break; + } + } -+ ++ + if (!subvol_found) + continue; + } + -+ if (get_fdinfo(pid, direntry->d_name, &fd) != 0) ++ if (fdret != 0) + continue; -+ -+ if (subvol_found && fd.mnt_id != dev_tmp->mnt_id) -+ continue; -+ else if (thedev != dev_tmp->device) ++ if (fd.mnt_id != dev_tmp->mnt_id) continue; + if (access == ACCESS_FILE @@ -475,11 +494,11 @@ Signed-off-by: Werner Fink add_matched_proc(dev_tmp->name, pid, uid, ACCESS_FILEWR | -@@ -1620,9 +1752,10 @@ check_dir(const pid_t pid, const char *d +@@ -1620,9 +1754,10 @@ check_dir(const pid_t pid, const char *d continue; } if (st.st_ino == ino_tmp->inode) { -+ if (get_fdinfo(pid, direntry->d_name, &fd) != 0) ++ if (fdret != 0) + continue; if (access == ACCESS_FILE - && (lstat(filepath, &lst) == 0) @@ -488,7 +507,7 @@ Signed-off-by: Werner Fink add_matched_proc(ino_tmp->name, pid, uid, ACCESS_FILEWR | -@@ -1651,31 +1784,54 @@ check_map(const pid_t pid, const char *f +@@ -1651,31 +1786,54 @@ check_map(const pid_t pid, const char *f FILE *fp; unsigned long long tmp_inode; unsigned int tmp_maj, tmp_min; @@ -553,7 +572,7 @@ Signed-off-by: Werner Fink } fclose(fp); } -@@ -1699,6 +1855,7 @@ static uid_t getpiduid(const pid_t pid) +@@ -1699,6 +1857,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 */ @@ -561,7 +580,7 @@ Signed-off-by: Werner Fink void fill_unix_cache(struct unixsocket_list **unixsocket_head) { FILE *fp; -@@ -1715,6 +1872,8 @@ void fill_unix_cache(struct unixsocket_l +@@ -1715,6 +1874,8 @@ void fill_unix_cache(struct unixsocket_l while (fgets(line, BUFSIZ, fp) != NULL) { char *path; char *scanned_path = NULL; @@ -570,7 +589,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 +1889,8 @@ void fill_unix_cache(struct unixsocket_l +@@ -1730,6 +1891,8 @@ void fill_unix_cache(struct unixsocket_l free(path); continue; } @@ -579,7 +598,7 @@ Signed-off-by: Werner Fink if ((newsocket = (struct unixsocket_list *) malloc(sizeof(struct unixsocket_list))) == NULL) { free(path); -@@ -1738,6 +1899,7 @@ void fill_unix_cache(struct unixsocket_l +@@ -1738,6 +1901,7 @@ void fill_unix_cache(struct unixsocket_l newsocket->sun_name = strdup(scanned_path); newsocket->inode = st.st_ino; newsocket->dev = st.st_dev; @@ -587,7 +606,7 @@ Signed-off-by: Werner Fink newsocket->net_inode = scanned_inode; newsocket->next = *unixsocket_head; *unixsocket_head = newsocket; -@@ -1750,6 +1912,7 @@ void fill_unix_cache(struct unixsocket_l +@@ -1750,6 +1914,7 @@ void fill_unix_cache(struct unixsocket_l /* * Free up the list of Unix sockets */ @@ -595,7 +614,7 @@ Signed-off-by: Werner Fink void clear_unix_cache(struct unixsocket_list **unixsocket_head) { while(*unixsocket_head != NULL) { -@@ -1921,34 +2084,21 @@ scan_mounts(struct names *names_head, st +@@ -1921,34 +2086,21 @@ scan_mounts(struct names *names_head, st { struct device_list *dev_tmp; struct inode_list *ino_tmp; @@ -638,7 +657,7 @@ Signed-off-by: Werner Fink add_special_proc(dev_tmp->name, PTYPE_MOUNT, 0, find_mountp); } -@@ -1960,7 +2110,6 @@ scan_mounts(struct names *names_head, st +@@ -1960,7 +2112,6 @@ scan_mounts(struct names *names_head, st find_mountp); } } @@ -646,7 +665,7 @@ Signed-off-by: Werner Fink } static void -@@ -2013,16 +2162,44 @@ scan_swaps(struct names *names_head, str +@@ -2013,16 +2164,44 @@ scan_swaps(struct names *names_head, str fclose(fp); } @@ -695,7 +714,7 @@ Signed-off-by: Werner Fink { list_t *ptr, *tmp; -@@ -2033,72 +2210,247 @@ static void clear_mntinfo(void) +@@ -2033,72 +2212,276 @@ static void clear_mntinfo(void) } } @@ -719,6 +738,11 @@ 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 @@ -734,16 +758,6 @@ 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; @@ -754,7 +768,16 @@ 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) @@ -780,41 +803,48 @@ 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) ++#if defined(HAS_FDINFO) /* Here we get the private namespace as well */ + 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; ++ goto out; /* forbidden namesspace, try our own namespace */ + while (fgets(line, BUFSIZ, fp) && ret < 2) { -+ char *fp, *vp, *ep; ++ char *xp, *vp, *ep; + unsigned long ul; -+ fp = strtok(&line[0], delimiters); -+ if (!fp || *fp == 0) ++ xp = strtok(&line[0], delimiters); ++ if (!xp || *xp == 0) + continue; + vp = strtok(NULL, delimiters); + if (!vp || *vp == 0) + continue; -+ if (strcmp(fp, "flags") == 0 && (ul = strtoul(vp, &ep, 0)) != ULONG_MAX && ep && *ep == 0) { ++ if (strcmp(xp, "flags") == 0 && (ul = strtoul(vp, &ep, 0)) != ULONG_MAX && ep && *ep == 0) { + info->flags = (mode_t)ul; + flags++; + ret++; + } -+ if (strcmp(fp, "mnt_id") == 0 && (ul = strtoul(vp, &ep, 0)) != ULONG_MAX && ep && *ep == 0) { ++ if (strcmp(xp, "mnt_id") == 0 && (ul = strtoul(vp, &ep, 0)) != ULONG_MAX && ep && *ep == 0) { + info->mnt_id = (int)ul; + mnt_id++; + ret++; @@ -822,6 +852,18 @@ 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; @@ -846,7 +888,12 @@ 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) @@ -988,7 +1035,7 @@ Signed-off-by: Werner Fink /* * Determine device of links below /proc/ */ -@@ -2106,8 +2458,7 @@ static int mntstat(const char *path, str +@@ -2106,8 +2489,7 @@ static int mntstat(const char *path, str { char name[PATH_MAX + 1]; const char *use; @@ -998,7 +1045,7 @@ Signed-off-by: Werner Fink if ((use = realpath(path, name)) == NULL || *use != '/') { -@@ -2119,27 +2470,26 @@ static int mntstat(const char *path, str +@@ -2119,27 +2501,26 @@ static int mntstat(const char *path, str errno = 0; return stat(path, buf); } @@ -1045,7 +1092,7 @@ Signed-off-by: Werner Fink #endif /* WITH_MOUNTINFO_LIST */ --- src/fuser.h -+++ src/fuser.h 2021-03-05 13:57:45.215585084 +0000 ++++ src/fuser.h 2021-05-07 15:01:31.954757006 +0000 @@ -37,10 +37,16 @@ struct procs { #define PTYPE_KNFSD 2 #define PTYPE_SWAP 3 @@ -1124,7 +1171,7 @@ Signed-off-by: Werner Fink #define PROC_MOUNTS "/proc/mounts" #define PROC_SWAPS "/proc/swaps" --- src/timeout.c -+++ src/timeout.c 2021-03-05 13:57:45.215585084 +0000 ++++ src/timeout.c 2021-05-07 15:01:31.954757006 +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 d3c9eb1..e80c5a9 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 9f3910df62bcc1f726b8e84f9ffc40c4d7916eac Mon Sep 17 00:00:00 2001 +From f2ada8ea7939bc8f607d88a10c92d5bb96a700b8 Mon Sep 17 00:00:00 2001 From: Werner Fink -Date: Thu, 14 Jan 2021 11:37:46 +0100 +Date: Fri, 7 May 2021 16:36:28 +0200 Subject: [PATCH] Use new statx(2) system call to avoid hangs on NFS Signed-off-by: Werner Fink --- Makefile.am | 4 - - configure.ac | 38 +++++---------- - src/fuser.c | 98 +++++++++----------------------------- + configure.ac | 24 +++++---- + src/fuser.c | 102 ++++++++++------------------------------ src/statx.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/statx.h | 68 ++++++++++++++++++++++++++ - 5 files changed, 258 insertions(+), 99 deletions(-) + 5 files changed, 260 insertions(+), 87 deletions(-) --- Makefile.am -+++ Makefile.am 2021-01-14 11:29:22.011223930 +0000 ++++ Makefile.am 2021-05-07 15:04:28.611513529 +0000 @@ -64,8 +64,8 @@ src_fuser_SOURCES = \ src/fuser.h \ src/lists.h @@ -26,29 +26,8 @@ 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-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 ++++ configure.ac 2021-05-07 15:04:28.623513310 +0000 +@@ -57,16 +57,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])]) @@ -80,8 +59,8 @@ Signed-off-by: Werner Fink # Enable hardened compile and link flags AC_ARG_ENABLE([harden_flags], --- src/fuser.c -+++ src/fuser.c 2021-01-14 11:30:10.750278604 +0000 -@@ -63,7 +63,7 @@ ++++ src/fuser.c 2021-05-07 15:04:28.627513237 +0000 +@@ -61,7 +61,7 @@ #include "fuser.h" #include "signals.h" #include "i18n.h" @@ -90,9 +69,9 @@ Signed-off-by: Werner Fink #include "comm.h" //#define DEBUG 1 -@@ -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); +@@ -119,10 +119,6 @@ static int get_fdinfo(const pid_t pid, c + 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); @@ -101,7 +80,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; -@@ -509,7 +505,7 @@ int parse_file(struct names *this_name, +@@ -510,7 +506,7 @@ int parse_file(struct names *this_name, free(this_name->filename); this_name->filename = strdup(new); } @@ -110,7 +89,7 @@ Signed-off-by: Werner Fink find_mountpoint(this_name->filename, &mountinfo) != 0) { if (errno == ENOENT) fprintf(stderr, -@@ -1245,9 +1241,7 @@ int main(int argc, char *argv[]) +@@ -1244,9 +1240,7 @@ int main(int argc, char *argv[]) opts |= OPT_INTERACTIVE; break; case 'I': @@ -120,7 +99,7 @@ Signed-off-by: Werner Fink break; case 'k': opts |= OPT_KILL; -@@ -1313,10 +1307,11 @@ int main(int argc, char *argv[]) +@@ -1312,10 +1306,11 @@ int main(int argc, char *argv[]) continue; } @@ -135,7 +114,7 @@ Signed-off-by: Werner Fink /* an option */ /* Not an option, must be a file specification */ if ((this_name = malloc(sizeof(struct names))) == NULL) -@@ -1636,7 +1631,7 @@ static struct stat *get_pidstat(const pi +@@ -1635,7 +1630,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); @@ -144,7 +123,7 @@ Signed-off-by: Werner Fink free(st); return NULL; } -@@ -1683,7 +1678,7 @@ check_dir(const pid_t pid, const char *d +@@ -1681,7 +1676,7 @@ check_dir(const pid_t pid, const char *d snprintf(filepath, sizeof filepath - 1, "/proc/%d/%s/%s", pid, dirname, direntry->d_name); @@ -153,7 +132,7 @@ Signed-off-by: Werner Fink if (errno != ENOENT && errno != ENOTDIR) { fprintf(stderr, _("Cannot stat file %s: %s\n"), filepath, strerror(errno)); -@@ -1740,7 +1735,7 @@ check_dir(const pid_t pid, const char *d +@@ -1747,7 +1742,7 @@ check_dir(const pid_t pid, const char *d if (thedev != ino_tmp->device) continue; if (!st.st_ino @@ -162,7 +141,7 @@ Signed-off-by: Werner Fink fprintf(stderr, _("Cannot stat file %s: %s\n"), filepath, strerror(errno)); -@@ -1838,11 +1833,11 @@ static uid_t getpiduid(const pid_t pid) +@@ -1845,11 +1840,11 @@ static uid_t getpiduid(const pid_t pid) if (asprintf(&pathname, "/proc/%d", pid) < 0) return 0; @@ -178,7 +157,7 @@ Signed-off-by: Werner Fink return st.st_uid; } -@@ -1880,7 +1875,7 @@ void fill_unix_cache(struct unixsocket_l +@@ -1887,7 +1882,7 @@ void fill_unix_cache(struct unixsocket_l path = scanned_path; if (*scanned_path == '@') scanned_path++; @@ -187,7 +166,7 @@ Signed-off-by: Werner Fink free(path); continue; } -@@ -2015,7 +2010,7 @@ static dev_t find_net_dev(void) +@@ -2022,7 +2017,7 @@ static dev_t find_net_dev(void) fprintf(stderr, _("Cannot open a network socket.\n")); return -1; } @@ -196,7 +175,7 @@ Signed-off-by: Werner Fink fprintf(stderr, _("Cannot find socket's device number.\n")); close(skt); return -1; -@@ -2052,7 +2047,7 @@ scan_knfsd(struct names *names_head, str +@@ -2059,7 +2054,7 @@ scan_knfsd(struct names *names_head, str if ((find_space = strpbrk(line, " \t")) == NULL) continue; *find_space = '\0'; @@ -205,7 +184,7 @@ Signed-off-by: Werner Fink continue; } /* Scan the devices */ -@@ -2086,7 +2081,7 @@ scan_mounts(struct names *names_head, st +@@ -2093,7 +2088,7 @@ scan_mounts(struct names *names_head, st mntinfo_t *mnt = list_entry(ptr, mntinfo_t); const char *find_mountp = mnt->mpoint; @@ -214,7 +193,7 @@ Signed-off-by: Werner Fink continue; /* Scan the devices */ -@@ -2136,7 +2131,7 @@ scan_swaps(struct names *names_head, str +@@ -2143,7 +2138,7 @@ scan_swaps(struct names *names_head, str if (*find_space == '\0') continue; } @@ -223,7 +202,7 @@ Signed-off-by: Werner Fink continue; } /* Scan the devices */ -@@ -2228,10 +2223,10 @@ init_mntinfo(void) +@@ -2240,10 +2235,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)); @@ -236,7 +215,7 @@ Signed-off-by: Werner Fink mntinf->dev = st.st_dev; /* stat(2) on binary does not see subvol dev */ } } -@@ -2243,7 +2238,7 @@ init_mntinfo(void) +@@ -2255,7 +2250,7 @@ init_mntinfo(void) parid = -1; while (fscanf (mnt, "%s %s %s %*[^\n]", &devname[0], &mpoint[0], &type[0]) == 3) { struct stat st; @@ -245,7 +224,7 @@ Signed-off-by: Werner Fink if (errno != EACCES) { fprintf(stderr, _("Cannot stat %s: %s\n"), mpoint, strerror(errno)); -@@ -2252,7 +2247,7 @@ init_mntinfo(void) +@@ -2264,7 +2259,7 @@ init_mntinfo(void) st.st_dev = (dev_t)-1; } mntinf = add_mntinfo(mpoint, type, mid++, parid, st.st_dev); @@ -254,7 +233,25 @@ Signed-off-by: Werner Fink if (st.st_rdev != 0 && mntinf->dev != st.st_rdev) mntinf->vol = st.st_rdev; } -@@ -2302,7 +2297,7 @@ out: +@@ -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: struct stat lst; snprintf(pathname, 256, "/proc/%d/fd/%s", pid, fd); @@ -263,7 +260,7 @@ Signed-off-by: Werner Fink if (lst.st_mode & S_IWUSR) info->flags |= O_WRONLY; ret++; -@@ -2375,7 +2370,7 @@ find_mountpoint(const char *path, mntinf +@@ -2411,7 +2406,7 @@ find_mountpoint(const char *path, mntinf /* could be a chroot or a container */ @@ -272,7 +269,7 @@ Signed-off-by: Werner Fink if (errno != EACCES) { fprintf(stderr, _("Cannot stat %s: %s\n"), path, strerror(errno)); -@@ -2407,7 +2402,7 @@ find_mountpoint(const char *path, mntinf +@@ -2443,7 +2438,7 @@ find_mountpoint(const char *path, mntinf /* could be a chroot or a container */ @@ -281,7 +278,7 @@ Signed-off-by: Werner Fink if (errno != EACCES) { fprintf(stderr, _("Cannot stat %s: %s\n"), use, strerror(errno)); -@@ -2445,49 +2440,6 @@ out: +@@ -2481,49 +2476,6 @@ out: return ret; } @@ -332,7 +329,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-01-14 11:29:22.015223853 +0000 ++++ src/statx.c 2021-05-07 15:04:28.627513237 +0000 @@ -0,0 +1,149 @@ +/* + * statx.c - Map modern statx(2) system call to older stat(2), lstat(2), @@ -484,7 +481,7 @@ Signed-off-by: Werner Fink + return ret; +} --- src/statx.h -+++ src/statx.h 2021-01-14 11:29:22.019223776 +0000 ++++ src/statx.h 2021-05-07 15:04:28.627513237 +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 aa80e2a..bcf9772 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 -@@ -129,7 +129,7 @@ AC_CHECK_MEMBERS([struct user_regs_struc +@@ -145,7 +145,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 -@@ -1146,6 +1146,7 @@ int main(int argc, char *argv[]) +@@ -1145,6 +1145,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'}, -@@ -1189,6 +1190,7 @@ int main(int argc, char *argv[]) +@@ -1188,6 +1189,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 */ -@@ -1333,6 +1335,7 @@ int main(int argc, char *argv[]) +@@ -1332,6 +1334,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); -@@ -1386,7 +1389,7 @@ int main(int argc, char *argv[]) +@@ -1385,7 +1388,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 4f7e8ce..4443366 100644 --- a/psmisc.changes +++ b/psmisc.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +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 fa6e13e..3263ed3 100644 --- a/psmisc.spec +++ b/psmisc.spec @@ -23,6 +23,8 @@ 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 @@ -94,13 +96,16 @@ 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 -%{_bindir}/fuser +%verify(not mode caps) %{_bindir}/fuser %{_bindir}/killall %ifarch %have_peekfd %{_bindir}/peekfd