From 4f1c05aa229e317a22169c320edde5284851e335 Mon Sep 17 00:00:00 2001 From: Guenther Deschner Date: Jan 27 2010 16:33:13 +0000 Subject: Security Release, fixes CVE-2009-3297 resolves: #532940 Guenther --- diff --git a/samba-3.4.5-CVE-2009-3297-mount_cifs.patch b/samba-3.4.5-CVE-2009-3297-mount_cifs.patch new file mode 100644 index 0000000..c42079d --- /dev/null +++ b/samba-3.4.5-CVE-2009-3297-mount_cifs.patch @@ -0,0 +1,628 @@ +From 40520b65fcfba963e90dfcffe87acd63a1760881 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Tue, 26 Jan 2010 08:45:53 -0500 +Subject: [PATCH 1/5] mount.cifs: directly include sys/stat.h in mtab.c + +This file is mysteriously getting included when built via the makefile, +but when you try to build mtab.o by hand it fails to build. Directly +include it to remove any ambiguity. + +Signed-off-by: Jeff Layton +--- + source3/client/mtab.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/source3/client/mtab.c b/source3/client/mtab.c +index 93fbd11..70789bc 100644 +--- a/source3/client/mtab.c ++++ b/source3/client/mtab.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include + #include + #include +-- +1.6.6 + +From 59dd0bb8c8b46c875bcc8b55a6c22fee5ea2113b Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Tue, 26 Jan 2010 08:45:57 -0500 +Subject: [PATCH 2/5] mount.cifs: properly check for mount being in fstab when running setuid root (try#3) + +This is the third attempt to clean up the checks when a setuid +mount.cifs is run by an unprivileged user. The main difference in this +patch from the last one is that it fixes a bug where the mount might +have failed if unnecessarily if CIFS_LEGACY_SETUID_CHECK was set. + +When mount.cifs is installed setuid root and run as an unprivileged +user, it does some checks to limit how the mount is used. It checks that +the mountpoint is owned by the user doing the mount. + +These checks however do not match those that /bin/mount does when it is +called by an unprivileged user. When /bin/mount is called by an +unprivileged user to do a mount, it checks that the mount in question is +in /etc/fstab, that it has the "user" option set, etc. + +This means that it's currently not possible to set up user mounts the +standard way (by the admin, in /etc/fstab) and simultaneously protect +from an unprivileged user calling mount.cifs directly to mount a share +on any directory that that user owns. + +Fix this by making the checks in mount.cifs match those of /bin/mount +itself. This is a necessary step to make mount.cifs safe to be installed +as a setuid binary, but not sufficient. For that, we'd need to give +mount.cifs a proper security audit. + +Since some users may be depending on the legacy behavior, this patch +also adds the ability to build mount.cifs with the older behavior. + +Signed-off-by: Jeff Layton +--- + source3/client/mount.cifs.c | 202 ++++++++++++++++++++++++++++++++++--------- + 1 files changed, 162 insertions(+), 40 deletions(-) + +diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c +index 43dc7f6..da2867c 100644 +--- a/source3/client/mount.cifs.c ++++ b/source3/client/mount.cifs.c +@@ -39,10 +39,11 @@ + #include + #include + #include ++#include + #include "mount.h" + + #define MOUNT_CIFS_VERSION_MAJOR "1" +-#define MOUNT_CIFS_VERSION_MINOR "12" ++#define MOUNT_CIFS_VERSION_MINOR "13" + + #ifndef MOUNT_CIFS_VENDOR_SUFFIX + #ifdef _SAMBA_BUILD_ +@@ -69,6 +70,10 @@ + #define MS_BIND 4096 + #endif + ++/* private flags - clear these before passing to kernel */ ++#define MS_USERS 0x40000000 ++#define MS_USER 0x80000000 ++ + #define MAX_UNC_LEN 1024 + + #define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr))) +@@ -83,6 +88,27 @@ + /* currently maximum length of IPv6 address string */ + #define MAX_ADDRESS_LEN INET6_ADDRSTRLEN + ++/* ++ * By default, mount.cifs follows the conventions set forth by /bin/mount ++ * for user mounts. That is, it requires that the mount be listed in ++ * /etc/fstab with the "user" option when run as an unprivileged user and ++ * mount.cifs is setuid root. ++ * ++ * Older versions of mount.cifs however were "looser" in this regard. When ++ * made setuid root, a user could run mount.cifs directly and mount any share ++ * on a directory owned by that user. ++ * ++ * The legacy behavior is now disabled by default. To reenable it, set the ++ * following #define to true. ++ */ ++#define CIFS_LEGACY_SETUID_CHECK 0 ++ ++/* ++ * When an unprivileged user runs a setuid mount.cifs, we set certain mount ++ * flags by default. These defaults can be changed here. ++ */ ++#define CIFS_SETUID_FLAGS (MS_NOSUID|MS_NODEV) ++ + const char *thisprogram; + int verboseflag = 0; + int fakemnt = 0; +@@ -142,6 +168,99 @@ static size_t strlcat(char *d, const char *s, size_t bufsize) + } + #endif + ++/* ++ * If an unprivileged user is doing the mounting then we need to ensure ++ * that the entry is in /etc/fstab. ++ */ ++static int ++check_mountpoint(const char *progname, char *mountpoint) ++{ ++ int err; ++ struct stat statbuf; ++ ++ /* does mountpoint exist and is it a directory? */ ++ err = stat(mountpoint, &statbuf); ++ if (err) { ++ fprintf(stderr, "%s: failed to stat %s: %s\n", progname, ++ mountpoint, strerror(errno)); ++ return EX_USAGE; ++ } ++ ++ if (!S_ISDIR(statbuf.st_mode)) { ++ fprintf(stderr, "%s: %s is not a directory!", progname, ++ mountpoint); ++ return EX_USAGE; ++ } ++ ++#if CIFS_LEGACY_SETUID_CHECK ++ /* do extra checks on mountpoint for legacy setuid behavior */ ++ if (!getuid() || geteuid()) ++ return 0; ++ ++ if (statbuf.st_uid != getuid()) { ++ fprintf(stderr, "%s: %s is not owned by user\n", progname, ++ mountpoint); ++ return EX_USAGE; ++ } ++ ++ if ((statbuf.st_mode & S_IRWXU) != S_IRWXU) { ++ fprintf(stderr, "%s: invalid permissions on %s\n", progname, ++ mountpoint); ++ return EX_USAGE; ++ } ++#endif /* CIFS_LEGACY_SETUID_CHECK */ ++ ++ return 0; ++} ++ ++#if CIFS_LEGACY_SETUID_CHECK ++static int ++check_fstab(const char *progname, char *mountpoint, char *devname, ++ char **options) ++{ ++ return 0; ++} ++#else /* CIFS_LEGACY_SETUID_CHECK */ ++static int ++check_fstab(const char *progname, char *mountpoint, char *devname, ++ char **options) ++{ ++ FILE *fstab; ++ struct mntent *mnt; ++ ++ /* make sure this mount is listed in /etc/fstab */ ++ fstab = setmntent(_PATH_FSTAB, "r"); ++ if (!fstab) { ++ fprintf(stderr, "Couldn't open %s for reading!\n", ++ _PATH_FSTAB); ++ return EX_FILEIO; ++ } ++ ++ while((mnt = getmntent(fstab))) { ++ if (!strcmp(mountpoint, mnt->mnt_dir)) ++ break; ++ } ++ endmntent(fstab); ++ ++ if (mnt == NULL || strcmp(mnt->mnt_fsname, devname)) { ++ fprintf(stderr, "%s: permission denied: no match for " ++ "%s found in %s\n", progname, mountpoint, ++ _PATH_FSTAB); ++ return EX_USAGE; ++ } ++ ++ /* ++ * 'mount' munges the options from fstab before passing them ++ * to us. It is non-trivial to test that we have the correct ++ * set of options. We don't want to trust what the user ++ * gave us, so just take whatever is in /etc/fstab. ++ */ ++ free(*options); ++ *options = strdup(mnt->mnt_opts); ++ return 0; ++} ++#endif /* CIFS_LEGACY_SETUID_CHECK */ ++ + /* BB finish BB + + cifs_umount +@@ -373,7 +492,7 @@ static int get_password_from_file(int file_descript, char * filename) + return rc; + } + +-static int parse_options(char ** optionsp, int * filesys_flags) ++static int parse_options(char ** optionsp, unsigned long * filesys_flags) + { + const char * data; + char * percent_char = NULL; +@@ -423,6 +542,7 @@ static int parse_options(char ** optionsp, int * filesys_flags) + + if (strncmp(data, "users",5) == 0) { + if(!value || !*value) { ++ *filesys_flags |= MS_USERS; + goto nocopy; + } + } else if (strncmp(data, "user_xattr",10) == 0) { +@@ -431,10 +551,7 @@ static int parse_options(char ** optionsp, int * filesys_flags) + + if (!value || !*value) { + if(data[4] == '\0') { +- if(verboseflag) +- printf("\nskipping empty user mount parameter\n"); +- /* remove the parm since it would otherwise be confusing +- to the kernel code which would think it was a real username */ ++ *filesys_flags |= MS_USER; + goto nocopy; + } else { + printf("username specified with no parameter\n"); +@@ -1046,7 +1163,7 @@ static void print_cifs_mount_version(void) + int main(int argc, char ** argv) + { + int c; +- int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */ ++ unsigned long flags = MS_MANDLOCK; + char * orgoptions = NULL; + char * share_name = NULL; + const char * ipaddr = NULL; +@@ -1069,7 +1186,6 @@ int main(int argc, char ** argv) + size_t current_len; + int retry = 0; /* set when we have to retry mount with uppercase */ + struct addrinfo *addrhead = NULL, *addr; +- struct stat statbuf; + struct utsname sysinfo; + struct mntent mountent; + struct sockaddr_in *addr4; +@@ -1127,8 +1243,8 @@ int main(int argc, char ** argv) + exit(EX_USAGE); + } + +- /* add sharename in opts string as unc= parm */ + ++ /* add sharename in opts string as unc= parm */ + while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:", + longopts, NULL)) != -1) { + switch (c) { +@@ -1266,6 +1382,22 @@ int main(int argc, char ** argv) + exit(EX_USAGE); + } + ++ /* make sure mountpoint is legit */ ++ rc = check_mountpoint(thisprogram, mountpoint); ++ if (rc) ++ goto mount_exit; ++ ++ /* sanity check for unprivileged mounts */ ++ if (getuid()) { ++ rc = check_fstab(thisprogram, mountpoint, dev_name, ++ &orgoptions); ++ if (rc) ++ goto mount_exit; ++ ++ /* enable any default user mount flags */ ++ flags |= CIFS_SETUID_FLAGS; ++ } ++ + if (getenv("PASSWD")) { + if(mountpassword == NULL) + mountpassword = (char *)calloc(MOUNT_PASSWD_SIZE+1,1); +@@ -1283,6 +1415,27 @@ int main(int argc, char ** argv) + rc = EX_USAGE; + goto mount_exit; + } ++ ++ if (getuid()) { ++#if !CIFS_LEGACY_SETUID_CHECK ++ if (!(flags & (MS_USERS|MS_USER))) { ++ fprintf(stderr, "%s: permission denied\n", thisprogram); ++ rc = EX_USAGE; ++ goto mount_exit; ++ } ++#endif /* !CIFS_LEGACY_SETUID_CHECK */ ++ ++ if (geteuid()) { ++ fprintf(stderr, "%s: not installed setuid - \"user\" " ++ "CIFS mounts not supported.", ++ thisprogram); ++ rc = EX_FAIL; ++ goto mount_exit; ++ } ++ } ++ ++ flags &= ~(MS_USERS|MS_USER); ++ + addrhead = addr = parse_server(&share_name); + if((addrhead == NULL) && (got_ip == 0)) { + printf("No ip address specified and hostname not found\n"); +@@ -1299,37 +1452,6 @@ int main(int argc, char ** argv) + mountpoint = resolved_path; + } + } +- if(chdir(mountpoint)) { +- printf("mount error: can not change directory into mount target %s\n",mountpoint); +- rc = EX_USAGE; +- goto mount_exit; +- } +- +- if(stat (".", &statbuf)) { +- printf("mount error: mount point %s does not exist\n",mountpoint); +- rc = EX_USAGE; +- goto mount_exit; +- } +- +- if (S_ISDIR(statbuf.st_mode) == 0) { +- printf("mount error: mount point %s is not a directory\n",mountpoint); +- rc = EX_USAGE; +- goto mount_exit; +- } +- +- if((getuid() != 0) && (geteuid() == 0)) { +- if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) { +-#ifndef CIFS_ALLOW_USR_SUID +- /* Do not allow user mounts to control suid flag +- for mount unless explicitly built that way */ +- flags |= MS_NOSUID | MS_NODEV; +-#endif +- } else { +- printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n"); +- exit(EX_USAGE); +- } +- } +- + if(got_user == 0) { + /* Note that the password will not be retrieved from the + USER env variable (ie user%password form) as there is +-- +1.6.6 + +From a92fa34e73b988ca84fe15df6f67ea4879a6aa2e Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Tue, 26 Jan 2010 08:45:58 -0500 +Subject: [PATCH 3/5] mount.cifs: take extra care that mountpoint isn't changed during mount + +It's possible to trick mount.cifs into mounting onto the wrong directory +by replacing the mountpoint with a symlink to a directory. mount.cifs +attempts to check the validity of the mountpoint, but there's still a +possible race between those checks and the mount(2) syscall. + +To guard against this, chdir to the mountpoint very early, and only deal +with it as "." from then on out. + +Signed-off-by: Jeff Layton +--- + source3/client/mount.cifs.c | 34 ++++++++++++++++++++++++++-------- + 1 files changed, 26 insertions(+), 8 deletions(-) + +diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c +index da2867c..53d1dad 100644 +--- a/source3/client/mount.cifs.c ++++ b/source3/client/mount.cifs.c +@@ -179,7 +179,7 @@ check_mountpoint(const char *progname, char *mountpoint) + struct stat statbuf; + + /* does mountpoint exist and is it a directory? */ +- err = stat(mountpoint, &statbuf); ++ err = stat(".", &statbuf); + if (err) { + fprintf(stderr, "%s: failed to stat %s: %s\n", progname, + mountpoint, strerror(errno)); +@@ -1383,6 +1383,14 @@ int main(int argc, char ** argv) + } + + /* make sure mountpoint is legit */ ++ rc = chdir(mountpoint); ++ if (rc) { ++ fprintf(stderr, "Couldn't chdir to %s: %s\n", mountpoint, ++ strerror(errno)); ++ rc = EX_USAGE; ++ goto mount_exit; ++ } ++ + rc = check_mountpoint(thisprogram, mountpoint); + if (rc) + goto mount_exit; +@@ -1445,13 +1453,23 @@ int main(int argc, char ** argv) + + /* BB save off path and pop after mount returns? */ + resolved_path = (char *)malloc(PATH_MAX+1); +- if(resolved_path) { +- /* Note that if we can not canonicalize the name, we get +- another chance to see if it is valid when we chdir to it */ +- if (realpath(mountpoint, resolved_path)) { +- mountpoint = resolved_path; +- } ++ if (!resolved_path) { ++ fprintf(stderr, "Unable to allocate memory.\n"); ++ rc = EX_SYSERR; ++ goto mount_exit; + } ++ ++ /* Note that if we can not canonicalize the name, we get ++ another chance to see if it is valid when we chdir to it */ ++ if(!realpath(".", resolved_path)) { ++ fprintf(stderr, "Unable to resolve %s to canonical path: %s\n", ++ mountpoint, strerror(errno)); ++ rc = EX_SYSERR; ++ goto mount_exit; ++ } ++ ++ mountpoint = resolved_path; ++ + if(got_user == 0) { + /* Note that the password will not be retrieved from the + USER env variable (ie user%password form) as there is +@@ -1585,7 +1603,7 @@ mount_retry: + if (verboseflag) + fprintf(stderr, "\n"); + +- if (!fakemnt && mount(dev_name, mountpoint, "cifs", flags, options)) { ++ if (!fakemnt && mount(dev_name, ".", "cifs", flags, options)) { + switch (errno) { + case ECONNREFUSED: + case EHOSTUNREACH: +-- +1.6.6 + +From bcdb9dc5d7daef6e93b742462e6dd056c0d1ed91 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Tue, 26 Jan 2010 08:45:58 -0500 +Subject: [PATCH 4/5] mount.cifs: check for invalid characters in device name and mountpoint + +It's apparently possible to corrupt the mtab if you pass embedded +newlines to addmntent. Apparently tabs are also a problem with certain +earlier glibc versions. Backslashes are also a minor issue apparently, +but we can't reasonably filter those. + +Make sure that neither the devname or mountpoint contain any problematic +characters before allowing the mount to proceed. + +Signed-off-by: Jeff Layton +--- + source3/client/mount.cifs.c | 34 ++++++++++++++++++++++++++++++++++ + 1 files changed, 34 insertions(+), 0 deletions(-) + +diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c +index 53d1dad..85be62b 100644 +--- a/source3/client/mount.cifs.c ++++ b/source3/client/mount.cifs.c +@@ -1160,6 +1160,36 @@ static void print_cifs_mount_version(void) + MOUNT_CIFS_VENDOR_SUFFIX); + } + ++/* ++ * This function borrowed from fuse-utils... ++ * ++ * glibc's addmntent (at least as of 2.10 or so) doesn't properly encode ++ * newlines embedded within the text fields. To make sure no one corrupts ++ * the mtab, fail the mount if there are embedded newlines. ++ */ ++static int check_newline(const char *progname, const char *name) ++{ ++ char *s; ++ for (s = "\n"; *s; s++) { ++ if (strchr(name, *s)) { ++ fprintf(stderr, "%s: illegal character 0x%02x in mount entry\n", ++ progname, *s); ++ return EX_USAGE; ++ } ++ } ++ return 0; ++} ++ ++static int check_mtab(const char *progname, const char *devname, ++ const char *dir) ++{ ++ if (check_newline(progname, devname) == -1 || ++ check_newline(progname, dir) == -1) ++ return EX_USAGE; ++ return 0; ++} ++ ++ + int main(int argc, char ** argv) + { + int c; +@@ -1603,6 +1633,10 @@ mount_retry: + if (verboseflag) + fprintf(stderr, "\n"); + ++ rc = check_mtab(thisprogram, dev_name, mountpoint); ++ if (rc) ++ goto mount_exit; ++ + if (!fakemnt && mount(dev_name, ".", "cifs", flags, options)) { + switch (errno) { + case ECONNREFUSED: +-- +1.6.6 + +From ea8a30a9d217127eb2e5a0e0cd27d943cae7d13a Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Tue, 26 Jan 2010 08:45:58 -0500 +Subject: [PATCH 5/5] mount.cifs: don't allow it to be run as setuid root program + +mount.cifs has been the subject of several "security" fire drills due to +distributions installing it as a setuid root program. This program has +not been properly audited for security and the Samba team highly +recommends that it not be installed as a setuid root program at this +time. + +To make that abundantly clear, this patch forcibly disables the ability +for mount.cifs to run as a setuid root program. People are welcome to +trivially patch this out, but they do so at their own peril. + +A security audit and redesign of this program is in progress and we hope +that we'll be able to remove this in the near future. + +Signed-off-by: Jeff Layton +--- + source3/client/mount.cifs.c | 39 ++++++++++++++++++++++++++++++++++++++- + 1 files changed, 38 insertions(+), 1 deletions(-) + +diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c +index 85be62b..f29e1e6 100644 +--- a/source3/client/mount.cifs.c ++++ b/source3/client/mount.cifs.c +@@ -43,7 +43,7 @@ + #include "mount.h" + + #define MOUNT_CIFS_VERSION_MAJOR "1" +-#define MOUNT_CIFS_VERSION_MINOR "13" ++#define MOUNT_CIFS_VERSION_MINOR "14" + + #ifndef MOUNT_CIFS_VENDOR_SUFFIX + #ifdef _SAMBA_BUILD_ +@@ -89,6 +89,17 @@ + #define MAX_ADDRESS_LEN INET6_ADDRSTRLEN + + /* ++ * mount.cifs has been the subject of many "security" bugs that have arisen ++ * because of users and distributions installing it as a setuid root program. ++ * mount.cifs has not been audited for security. Thus, we strongly recommend ++ * that it not be installed setuid root. To make that abundantly clear, ++ * mount.cifs now check whether it's running setuid root and exit with an ++ * error if it is. If you wish to disable this check, then set the following ++ * #define to 1, but please realize that you do so at your own peril. ++ */ ++#define CIFS_DISABLE_SETUID_CHECK 0 ++ ++/* + * By default, mount.cifs follows the conventions set forth by /bin/mount + * for user mounts. That is, it requires that the mount be listed in + * /etc/fstab with the "user" option when run as an unprivileged user and +@@ -213,6 +224,29 @@ check_mountpoint(const char *progname, char *mountpoint) + return 0; + } + ++#if CIFS_DISABLE_SETUID_CHECK ++static int ++check_setuid(void) ++{ ++ return 0; ++} ++#else /* CIFS_DISABLE_SETUID_CHECK */ ++static int ++check_setuid(void) ++{ ++ if (getuid() && !geteuid()) { ++ printf("This mount.cifs program has been built with the " ++ "ability to run as a setuid root program disabled.\n" ++ "mount.cifs has not been well audited for security " ++ "holes. Therefore the Samba team does not recommend " ++ "installing it as a setuid root program.\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++#endif /* CIFS_DISABLE_SETUID_CHECK */ ++ + #if CIFS_LEGACY_SETUID_CHECK + static int + check_fstab(const char *progname, char *mountpoint, char *devname, +@@ -1222,6 +1256,9 @@ int main(int argc, char ** argv) + struct sockaddr_in6 *addr6; + FILE * pmntfile; + ++ if (check_setuid()) ++ return EX_USAGE; ++ + /* setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); */ +-- +1.6.6 + diff --git a/samba.spec b/samba.spec index ee87b69..e367bec 100644 --- a/samba.spec +++ b/samba.spec @@ -1,4 +1,4 @@ -%define main_release 54 +%define main_release 55 %define samba_version 3.4.5 %define tdb_version 1.1.3 %define talloc_version 1.3.0 @@ -46,6 +46,7 @@ Patch104: samba-3.0.0rc3-nmbd-netbiosname.patch Patch107: samba-3.2.0pre1-grouppwd.patch Patch200: samba-3.2.5-inotify.patch Patch201: samba-3.4.5-pdbedit.patch +Patch202: samba-3.4.5-CVE-2009-3297-mount_cifs.patch Requires(pre): samba-common = %{epoch}:%{samba_version}-%{release} Requires: pam >= 0:0.64 @@ -204,6 +205,7 @@ cp %{SOURCE11} packaging/Fedora/ %patch107 -p1 -b .grouppwd %patch200 -p0 -b .inotify %patch201 -p1 -b .pdbedit +%patch202 -p1 -b .CVE-2009-3297-mount_cifs mv %samba_source/VERSION %samba_source/VERSION.orig sed -e 's/SAMBA_VERSION_VENDOR_SUFFIX=$/&\"%{samba_release}\"/' < %samba_source/VERSION.orig > %samba_source/VERSION @@ -656,6 +658,10 @@ exit 0 %{_datadir}/pixmaps/samba/logo-small.png %changelog +* Wed Jan 26 2010 Guenther Deschner - 3.4.5-55 +- Security Release, fixes CVE-2009-3297 +- resolves: #532940 + * Wed Jan 26 2010 Guenther Deschner - 3.4.5-54 - Fix crash in pdbedit - resolves: #541267