diff --git a/psmisc-22.6-fdleak.patch b/psmisc-22.6-fdleak.patch index 4b71eda..807b223 100644 --- a/psmisc-22.6-fdleak.patch +++ b/psmisc-22.6-fdleak.patch @@ -1,18 +1,5 @@ --- src/fuser.c +++ src/fuser.c 2008-09-01 15:03:05.054239318 +0200 -@@ -925,8 +925,10 @@ int main(int argc, char *argv[]) - continue; - } - -- scan_mount_devices(opts, &mount_devices); -- fill_unix_cache(&unixsockets); -+ if (!mount_devices) -+ scan_mount_devices(opts, &mount_devices); -+ if (!unixsockets) -+ fill_unix_cache(&unixsockets); - - /* File specifications */ - if ( (this_name = malloc(sizeof(struct names))) == NULL) @@ -1306,6 +1308,7 @@ void fill_unix_cache(struct unixsocket_l *unixsocket_head = newsocket; } /* while */ diff --git a/psmisc-22.6-nfs4fuser.patch b/psmisc-22.6-nfs4fuser.patch index 1fbe482..00343f1 100644 --- a/psmisc-22.6-nfs4fuser.patch +++ b/psmisc-22.6-nfs4fuser.patch @@ -33,8 +33,8 @@ cannot report on any processes that it doesn't have permission to look at the file descriptor table for. The most common time this problem occurs --- src/fuser.c -+++ src/fuser.c 2008-08-07 14:47:58.126764924 +0200 -@@ -32,6 +32,7 @@ ++++ src/fuser.c 2008-09-23 16:00:18.038188677 +0200 +@@ -32,9 +32,11 @@ #include #include #include @@ -42,7 +42,19 @@ #include #include #include -@@ -62,7 +63,7 @@ ++#include + #include + #include + #include +@@ -45,6 +47,7 @@ + #include + #include + #include ++#include + + #include "fuser.h" + #include "signals.h" +@@ -62,7 +65,7 @@ static void add_matched_proc(struct names *name_list, const pid_t pid, const uid_t uid, const char access); static void check_dir(const pid_t pid, const char *dirname, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access); static void check_map(const pid_t pid, const char *filename, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access); @@ -51,25 +63,27 @@ static uid_t getpiduid(const pid_t pid); static int print_matches(struct names *names_head, const opt_type opts, const int sig_number); static void kill_matched_proc(struct procs *pptr, const opt_type opts, const int sig_number); -@@ -72,13 +73,15 @@ static void add_device(struct device_lis +@@ -72,13 +75,18 @@ static void add_device(struct device_lis void scan_mount_devices(const opt_type opts, struct mountdev_list **mount_devices); void fill_unix_cache(struct unixsocket_list **unixsocket_head); static dev_t find_net_dev(void); -static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head); -+static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct mountdev_list *mounts); ++static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head); #ifdef NFS_CHECKS static void scan_knfsd(struct names *names_head, struct device_list *dev_head); #endif /* NFS_CHECKS */ #ifdef DEBUG --static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head); -+static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct mountdev_list *mounts); + static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head); #endif +static struct nfs_points *mnts; +static int check4nfs(const char * path, char * real); ++ ++typedef int (*stat_t)(const char*, struct stat*); ++static int nfssafe(stat_t func, const char *path, struct stat *buf); static void usage (const char *errormsg) { -@@ -127,7 +130,14 @@ void print_version() +@@ -127,7 +135,14 @@ void print_version() "For more information about these matters, see the files named COPYING.\n")); } @@ -81,11 +95,11 @@ + return (strstr(path, loc) == path); +} + -+static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct mountdev_list *mounts) ++static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head) { DIR *topproc_dir; struct dirent *topproc_dent; -@@ -137,6 +147,9 @@ static void scan_procs(struct names *nam +@@ -137,6 +152,9 @@ static void scan_procs(struct names *nam pid_t pid, my_pid; uid_t uid; struct stat *cwd_stat, *exe_stat, *root_stat; @@ -95,7 +109,7 @@ if ( (fd_dirpath = malloc(MAX_PATHNAME)) == NULL) return; -@@ -157,9 +170,10 @@ static void scan_procs(struct names *nam +@@ -157,9 +175,10 @@ static void scan_procs(struct names *nam continue; uid = getpiduid(pid); @@ -109,7 +123,7 @@ /* Scan the devices */ for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) { if (exe_stat != NULL && exe_stat->st_dev == dev_tmp->device) -@@ -168,6 +182,14 @@ static void scan_procs(struct names *nam +@@ -168,6 +187,14 @@ static void scan_procs(struct names *nam add_matched_proc(dev_tmp->name, pid, uid, ACCESS_ROOT); if (cwd_stat != NULL && cwd_stat->st_dev == dev_tmp->device) add_matched_proc(dev_tmp->name, pid, uid, ACCESS_CWD); @@ -124,7 +138,7 @@ } for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) { if (exe_stat != NULL) { -@@ -186,9 +208,19 @@ static void scan_procs(struct names *nam +@@ -186,9 +213,19 @@ static void scan_procs(struct names *nam add_matched_proc(ino_tmp->name, pid, uid, ACCESS_CWD); } } @@ -144,7 +158,7 @@ check_dir(pid, "fd", dev_head, ino_head, uid, ACCESS_FILE); check_map(pid, "maps", dev_head, ino_head, uid, ACCESS_MMAP); -@@ -325,10 +357,26 @@ int parse_mount(struct names *this_name, +@@ -325,10 +362,26 @@ int parse_mount(struct names *this_name, return 0; } @@ -172,7 +186,7 @@ if (stat(this_name->filename, &st) != 0) { fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename, strerror(errno)); -@@ -342,34 +390,44 @@ int parse_file(struct names *this_name, +@@ -342,34 +395,44 @@ int parse_file(struct names *this_name, return 0; } @@ -224,7 +238,7 @@ if (stat(this_name->filename, &st) != 0) { fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename, -@@ -388,6 +446,16 @@ int parse_mounts(struct names *this_name +@@ -388,6 +451,16 @@ int parse_mounts(struct names *this_name } } return 0; @@ -241,7 +255,7 @@ } #ifdef WITH_IPV6 -@@ -652,6 +720,80 @@ void find_net6_sockets(struct inode_list +@@ -652,6 +725,80 @@ void find_net6_sockets(struct inode_list } #endif @@ -322,49 +336,52 @@ int main(int argc, char *argv[]) { opt_type opts; -@@ -664,7 +806,7 @@ int main(int argc, char *argv[]) - struct device_list *match_devices = NULL; - struct unixsocket_list *unixsockets = NULL; +@@ -676,6 +823,7 @@ int main(int argc, char *argv[]) + int optc; + char *option; + char *nsptr; ++ size_t len; -- dev_t netdev; -+ dev_t netdev = find_net_dev(); - struct ip_connections *tcp_connection_list = NULL; - struct ip_connections *udp_connection_list = NULL; #ifdef WITH_IPV6 -@@ -691,10 +833,6 @@ int main(int argc, char *argv[]) - textdomain(PACKAGE); + ipv4_only = ipv6_only = 0; +@@ -692,7 +840,6 @@ int main(int argc, char *argv[]) #endif -- netdev = find_net_dev(); + netdev = find_net_dev(); - scan_mount_devices(opts, &mount_devices); -- fill_unix_cache(&unixsockets); -- + fill_unix_cache(&unixsockets); + /* getopt doesnt like things like -SIGBLAH */ - for(optc = 1; optc < argc; optc++) { - if (argv[optc][0] == '-') { /* its an option */ -@@ -782,6 +920,10 @@ int main(int argc, char *argv[]) +@@ -782,6 +929,10 @@ int main(int argc, char *argv[]) } continue; } + -+ scan_mount_devices(opts, &mount_devices); -+ fill_unix_cache(&unixsockets); ++ if (!mount_devices) ++ scan_mount_devices(opts, &mount_devices); + /* File specifications */ if ( (this_name = malloc(sizeof(struct names))) == NULL) continue; -@@ -828,8 +970,8 @@ int main(int argc, char *argv[]) +@@ -828,10 +979,14 @@ int main(int argc, char *argv[]) break; default: /* FILE */ this_name->filename = strdup(argv[optc]); - parse_file(this_name, &match_inodes); - parse_unixsockets(this_name, &match_inodes, unixsockets); +- if (opts & OPT_MOUNTPOINT || opts & OPT_MOUNTS) ++ len = strlen(this_name->filename); ++ if (this_name->filename[len-1] == '/') ++ this_name->filename[len-1] = '\0'; + parse_file(this_name, &match_inodes, opts); + parse_unixsockets(this_name, &match_inodes, unixsockets, netdev, opts); - if (opts & OPT_MOUNTPOINT || opts & OPT_MOUNTS) ++ if (opts & (OPT_MOUNTPOINT | OPT_MOUNTS)) { parse_mounts(this_name, mount_devices, &match_devices, opts); ++ } break; -@@ -857,22 +999,22 @@ int main(int argc, char *argv[]) + } + +@@ -857,22 +1012,22 @@ int main(int argc, char *argv[]) if (!ipv4_only) { #endif if (tcp_connection_list != NULL) @@ -385,15 +402,14 @@ } #endif #ifdef DEBUG -- debug_match_lists(names_head, match_inodes, match_devices); -+ debug_match_lists(names_head, match_inodes, match_devices, mount_devices); + debug_match_lists(names_head, match_inodes, match_devices); #endif - scan_procs(names_head, match_inodes, match_devices); -+ scan_procs(opts, names_head, match_inodes, match_devices, mount_devices); ++ scan_procs(opts, names_head, match_inodes, match_devices); #ifdef NFS_CHECKS scan_knfsd(names_head, match_devices); #endif /* NFS_CHECKS */ -@@ -978,7 +1120,7 @@ static int print_matches(struct names *n +@@ -978,7 +1133,7 @@ static int print_matches(struct names *n } @@ -402,7 +418,7 @@ { char pathname[256]; struct stat *st; -@@ -986,6 +1128,10 @@ static struct stat *get_pidstat(const pi +@@ -986,6 +1141,10 @@ static struct stat *get_pidstat(const pi if ( (st = malloc(sizeof(struct stat))) == NULL) return NULL; snprintf(pathname, 256, "/proc/%d/%s", pid, filename); @@ -413,7 +429,7 @@ if (stat(pathname, st) != 0) return NULL; else -@@ -1012,13 +1158,14 @@ static void check_dir(const pid_t pid, c +@@ -1012,13 +1171,14 @@ static void check_dir(const pid_t pid, c while ( (direntry = readdir(dirp)) != NULL) { if (direntry->d_name[0] < '0' || direntry->d_name[0] > '9') continue; @@ -429,7 +445,7 @@ if (st.st_dev == dev_tmp->device) { if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) { add_matched_proc(dev_tmp->name, pid,uid, ACCESS_FILEWR|access); -@@ -1028,6 +1175,8 @@ static void check_dir(const pid_t pid, c +@@ -1028,6 +1188,8 @@ static void check_dir(const pid_t pid, c } } for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) { @@ -438,7 +454,7 @@ if (st.st_dev == ino_tmp->device && st.st_ino == ino_tmp->inode) { if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) { add_matched_proc(ino_tmp->name, pid,uid, ACCESS_FILEWR|access); -@@ -1039,6 +1188,8 @@ static void check_dir(const pid_t pid, c +@@ -1039,6 +1201,8 @@ static void check_dir(const pid_t pid, c } } /* while fd_dent */ closedir(dirp); @@ -447,7 +463,7 @@ } static void check_map(const pid_t pid, const char *filename, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access) -@@ -1059,12 +1210,18 @@ static void check_map(const pid_t pid, c +@@ -1059,12 +1223,18 @@ static void check_map(const pid_t pid, c if (sscanf(line, "%*s %*s %*s %x:%x %lld", &tmp_maj, &tmp_min, &tmp_inode) == 3) { tmp_device = tmp_maj * 256 + tmp_min; @@ -468,7 +484,7 @@ } } fclose(fp); -@@ -1144,22 +1301,48 @@ void scan_mount_devices(const opt_type o +@@ -1144,17 +1314,53 @@ void scan_mount_devices(const opt_type o FILE *mntfp; struct mntent *mnt_ptr; struct stat st; @@ -488,7 +504,7 @@ while ( (mnt_ptr = getmntent(mntfp)) != NULL) { + if (!strcasecmp(MNTTYPE_NFS, mnt_ptr->mnt_type)) { + /* -+ * Remember all NFS typed partitions. ++ * Remember all NFS typed partitions, required to make check4nfs() work. + */ + struct nfs_points * p = (struct nfs_points*)malloc(sizeof(struct nfs_points)); + if (!p) @@ -506,9 +522,19 @@ + add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, (dev_t)-1); + continue; + } ++ if (nfssafe(stat, mnt_ptr->mnt_dir, &st) == 0) { ++ add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, st.st_dev); ++ } else { ++ fprintf(stderr, _("Cannot stat file %s: %s\n"), mnt_ptr->mnt_dir, strerror(errno)); ++ } ++ continue; + } ++ if ((opts & (OPT_MOUNTPOINT|OPT_MOUNTS)) == 0) ++ continue; if (stat(mnt_ptr->mnt_dir, &st) == 0) { add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, st.st_dev); ++ } else { ++ fprintf(stderr, _("Cannot stat file %s: %s\n"), mnt_ptr->mnt_dir, strerror(errno)); } } +out: @@ -516,14 +542,65 @@ } #ifdef DEBUG - /* often not used, doesnt need translation */ --static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head) -+static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, ) - { - struct names *nptr; - struct inode_list *iptr; +@@ -1280,3 +1486,56 @@ static void scan_knfsd(struct names *nam + } + } + #endif /* NFSCHECKS */ ++ ++static sigjmp_buf jenv; ++static int timeout = 5; ++static void sigalarm(int sig) ++{ ++ if (sig == SIGALRM) ++ siglongjmp(jenv, 1); ++} ++static int nfssafe(stat_t func, const char *path, struct stat *buf) ++{ ++ pid_t pid = 0; ++ int ret = 0, pipes[4]; ++ ++ if (pipe(&pipes[0]) < 0) ++ goto err; ++ switch ((pid = fork ())) { ++ case -1: ++ close(pipes[0]); ++ close(pipes[1]); ++ goto err; ++ case 0: ++ (void) signal(SIGALRM, SIG_DFL); ++ close(pipes[0]); ++ if ((ret = func(path, buf)) == 0) ++ write(pipes[1], buf, sizeof(struct stat)); ++ close(pipes[1]); ++ exit(ret); ++ default: ++ close(pipes[1]); ++ if (sigsetjmp(jenv, 1)) { ++ (void) alarm(0); ++ (void) signal(SIGALRM, SIG_DFL); ++ if (waitpid(0, (int*)0, WNOHANG) == 0) ++ kill(pid, SIGKILL); ++ errno = ETIMEDOUT; ++ timeout = 1; ++ goto err; ++ } ++ (void) signal(SIGALRM, sigalarm); ++ (void) alarm(timeout); ++ if (read(pipes[0], buf, sizeof(struct stat)) == 0) { ++ errno = EFAULT; ++ ret = -1; ++ } ++ (void) alarm(0); ++ (void) signal(SIGALRM, SIG_DFL); ++ close(pipes[0]); ++ break; ++ } ++ return ret; ++err: ++ return -1; ++} --- src/fuser.h -+++ src/fuser.h 2008-08-07 14:26:47.587191317 +0200 ++++ src/fuser.h 2008-08-07 14:26:48.000000000 +0200 @@ -80,9 +80,16 @@ struct unixsocket_list { struct unixsocket_list *next; }; diff --git a/psmisc.changes b/psmisc.changes index f96a54e..fa05247 100644 --- a/psmisc.changes +++ b/psmisc.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Tue Sep 23 15:30:58 CEST 2008 - werner@suse.de + +- Enhance NFS patch for fuser (bug #409011) + ------------------------------------------------------------------- Mon Sep 1 15:10:43 CEST 2008 - werner@suse.de diff --git a/psmisc.spec b/psmisc.spec index 943d344..fcc87c6 100644 --- a/psmisc.spec +++ b/psmisc.spec @@ -27,7 +27,7 @@ Group: System/Monitoring PreReq: %fillup_prereq %insserv_prereq AutoReqProv: on Version: 22.6 -Release: 52 +Release: 59 Provides: ps:/usr/bin/killall Summary: Utilities for managing processes on your system Source: http://switch.dl.sourceforge.net/sourceforge/psmisc/psmisc-%{version}.tar.bz2 @@ -103,6 +103,8 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man1/pstree.1* %changelog +* Tue Sep 23 2008 werner@suse.de +- Enhance NFS patch for fuser (bug #409011) * Mon Sep 01 2008 werner@suse.de - Do not leak on /proc/net/unix (bnc#417841) - Read /proc/net/unix and /proc/mounts only once