Hello community,
here is the log from the commit of package ncpfs for openSUSE:Factory
checked in at Wed May 5 22:59:46 CEST 2010.
--------
--- ncpfs/ncpfs.changes 2010-04-27 12:18:53.000000000 +0200
+++ ncpfs/ncpfs.changes 2010-05-05 11:08:26.000000000 +0200
@@ -1,0 +2,10 @@
+Wed May 5 11:07:55 CEST 2010 - meissner@suse.de
+
+- Fixed information leakage on mount (CVE-2010-0790 / bnc#583536)
+- Fixed mtab locking problem (CVE-2010-0791 / bnc#583536)
+ ncpfs-2_2_6_partial.patch
+
+- Fixed race condition in ncpfs mounts (CVE-2010-0788 / bnc#550004)
+ ncpfs-2.2.6-mount-issue-ver2.patch
+
+-------------------------------------------------------------------
calling whatdependson for head-i586
New:
----
ncpfs-2.2.6-mount-issue-ver2.patch
ncpfs-2_2_6_partial.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ncpfs.spec ++++++
--- /var/tmp/diff_new_pack.lxuxET/_old 2010-05-05 22:55:16.000000000 +0200
+++ /var/tmp/diff_new_pack.lxuxET/_new 2010-05-05 22:55:16.000000000 +0200
@@ -24,7 +24,7 @@
Group: Productivity/Networking/Novell
AutoReqProv: on
Version: 2.2.6
-Release: 160
+Release: 161
PreReq: %insserv_prereq %fillup_prereq
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Summary: Tools for Accessing Novell File Systems
@@ -94,6 +94,8 @@
Patch1003: ncpfs.pam_ncp_auth.syslog.patch
Patch1005: ncpfs.offsetof.patch
Patch1006: ncpfs.mount_hang.patch
+Patch1007: ncpfs-2.2.6-mount-issue-ver2.patch
+Patch1008: ncpfs-2_2_6_partial.patch
# In openSUSE 11.3 there is upstream compliant CUPS 1.4
# which means to have a fixed "/usr/lib/cups/" directory
# on all platforms (see Novell/Suse Bugzilla bnc#575544):
@@ -196,6 +198,8 @@
%patch1003 -p1
%patch1005 -p1
%patch1006 -p1
+%patch1007 -p1
+%patch1008 -p1
tar xfvj %{SOURCE12}
if [ "$UID" = 0 ] ; then chown -R 0:0 . ; fi
++++++ ncpfs-2.2.6-mount-issue-ver2.patch ++++++
Index: ncpfs-2.2.6/sutil/ncpm_common.c
===================================================================
--- ncpfs-2.2.6.orig/sutil/ncpm_common.c
+++ ncpfs-2.2.6/sutil/ncpm_common.c
@@ -444,7 +444,7 @@ static int ncp_mount_v2(const char* moun
}
datav2.file_mode = data->file_mode;
datav2.dir_mode = data->dir_mode;
- err = proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, (void*) &datav2);
+ err = proc_ncpm_mount(mount_name, ".", "ncpfs", flags, (void*) &datav2);
if (err)
return errno;
return 0;
@@ -508,7 +508,7 @@ static int ncp_mount_v3(const char* moun
exit(0); /* Should not return from process_connection */
}
close(pp[0]);
- err=proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, (void*) &datav3);
+ err=proc_ncpm_mount(mount_name, ".", "ncpfs", flags, (void*) &datav3);
if (err) {
err = errno;
/* Mount unsuccesful so we have to kill daemon */
@@ -559,7 +559,7 @@ static int ncp_mount_v4(const char* moun
sprintf(mountopts, "version=%u,flags=%u,owner=%u,uid=%u,gid=%u,mode=%u,dirmode=%u,timeout=%u,retry=%u,wdogpid=%u,ncpfd=%u,infofd=%u",
NCP_MOUNT_VERSION_V5, ncpflags, data->mounted_uid, data->uid, data->gid, data->file_mode,
data->dir_mode, data->time_out, data->retry_count, wdog_pid, data->ncp_fd, pp[1]);
- err=proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, mountopts);
+ err=proc_ncpm_mount(mount_name, ".", "ncpfs", flags, mountopts);
} else {
err=-1;
}
@@ -577,7 +577,7 @@ static int ncp_mount_v4(const char* moun
datav4.file_mode = data->file_mode;
datav4.dir_mode = data->dir_mode;
datav4.wdog_pid = wdog_pid;
- err = proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, (void*)&datav4);
+ err = proc_ncpm_mount(mount_name, ".", "ncpfs", flags, (void*)&datav4);
if (err) {
err = errno;
/* Mount unsuccesful so we have to kill daemon */
@@ -1395,6 +1395,17 @@ process_connection (const struct ncp_mou
}
#endif /* MOUNT3 */
+static int check_name(const char *name)
+{
+ char *s;
+ for (s = "\n\t\\"; *s; s++) {
+ if (strchr(name, *s)) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
static const struct smntflags {
unsigned int flag;
const char* name;
@@ -1416,6 +1427,9 @@ void add_mnt_entry(char* mount_name, cha
int fd;
FILE* mtab;
+ if (check_name(mount_name) == -1 || check_name(mpnt) == -1)
+ errexit(107, _("Illegal character in mount entry\n"));
+
ment.mnt_fsname = mount_name;
ment.mnt_dir = mpnt;
ment.mnt_type = (char*)"ncpfs";
Index: ncpfs-2.2.6/sutil/ncpmount.c
===================================================================
--- ncpfs-2.2.6.orig/sutil/ncpmount.c
+++ ncpfs-2.2.6/sutil/ncpmount.c
@@ -359,11 +359,17 @@ main(int argc, char *argv[])
usage();
return -1;
}
+
realpath(argv[optind], mount_point);
- if (stat(mount_point, &st) == -1)
+ if (chdir(mount_point))
+ {
+ errexit(31, _("Could not change directory into mount target %s: %s\n"),
+ mount_point, strerror(errno));
+ }
+ if (stat(".", &st) == -1)
{
- errexit(31, _("Could not find mount point %s: %s\n"),
+ errexit(31, _("Mount point %s does not exist: %s\n"),
mount_point, strerror(errno));
}
if (mount_ok(&st) != 0)
Index: ncpfs-2.2.6/sutil/ncpumount.c
===================================================================
--- ncpfs-2.2.6.orig/sutil/ncpumount.c
+++ ncpfs-2.2.6/sutil/ncpumount.c
@@ -61,6 +61,8 @@
#include
#include
#include
+#include
+#include
#include
#include
@@ -70,10 +72,19 @@
#include
#include
+#include
+
#include "private/libintl.h"
#define _(X) X
+#ifndef MS_REC
+#define MS_REC 16384
+#endif
+#ifndef MS_SLAVE
+#define MS_SLAVE (1<<19)
+#endif
+
static char *progname;
static int is_ncplogout = 0;
@@ -229,11 +240,188 @@ static int clearMtab (const char* mount_
return err;
}
+
+int ncp_mnt_umount(const char *abs_mnt, const char *rel_mnt)
+{
+ if (umount(rel_mnt) != 0) {
+ eprintf(_("Could not umount %s: %s\n"),
+ abs_mnt, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+
+static int check_is_mount_child(void *p)
+{
+ const char **a = p;
+ const char *last = a[0];
+ const char *mnt = a[1];
+ int res;
+ const char *procmounts = "/proc/mounts";
+ int found;
+ FILE *fp;
+ struct mntent *entp;
+
+ res = mount("", "/", "", MS_SLAVE | MS_REC, NULL);
+ if (res == -1) {
+ eprintf(_("Failed to mark mounts slave: %s\n"),
+ strerror(errno));
+ return 1;
+ }
+
+ res = mount(".", "/tmp", "", MS_BIND | MS_REC, NULL);
+ if (res == -1) {
+ eprintf(_("Failed to bind parent to /tmp: %s\n"),
+ strerror(errno));
+ return 1;
+ }
+
+ fp = setmntent(procmounts, "r");
+ if (fp == NULL) {
+ eprintf(_("Failed to open %s: %s\n"),
+ procmounts, strerror(errno));
+ return 1;
+ }
+
+ found = 0;
+ while ((entp = getmntent(fp)) != NULL) {
+ if (strncmp(entp->mnt_dir, "/tmp/", 5) == 0 &&
+ strcmp(entp->mnt_dir + 5, last) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ endmntent(fp);
+
+ if (!found) {
+ eprintf(_("%s not mounted\n"), mnt);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int check_is_mount(const char *last, const char *mnt)
+{
+ char buf[131072];
+ pid_t pid, p;
+ int status;
+ const char *a[2] = { last, mnt };
+
+ pid = clone(check_is_mount_child, buf + 65536, CLONE_NEWNS, (void *) a);
+ if (pid == (pid_t) -1) {
+ eprintf(_("Failed to clone namespace: %s\n"),
+ strerror(errno));
+ return -1;
+ }
+ p = waitpid(pid, &status, __WCLONE);
+ if (p == (pid_t) -1) {
+ eprintf(_("Waitpid failed: %s\n"),
+ strerror(errno));
+ return -1;
+ }
+ if (!WIFEXITED(status)) {
+ eprintf(_("Child terminated abnormally (status %i)\n"),
+ status);
+ return -1;
+ }
+ if (WEXITSTATUS(status) != 0)
+ return -1;
+
+ return 0;
+}
+
+
+static int chdir_to_parent(char *copy, const char **lastp, int *currdir_fd)
+{
+ char *tmp;
+ const char *parent;
+ char buf[PATH_MAX];
+ int res;
+
+ tmp = strrchr(copy, '/');
+ if (tmp == NULL || tmp[1] == '\0') {
+ eprintf(_("Internal error: invalid abs path: <%s>\n"),
+ copy);
+ return -1;
+ }
+ if (tmp != copy) {
+ *tmp = '\0';
+ parent = copy;
+ *lastp = tmp + 1;
+ } else if (tmp[1] != '\0') {
+ *lastp = tmp + 1;
+ parent = "/";
+ } else {
+ *lastp = ".";
+ parent = "/";
+ }
+ *currdir_fd = open(".", O_RDONLY);
+ if (*currdir_fd == -1) {
+ eprintf(_("Failed to open current directory: %s\n"),
+ strerror(errno));
+ return -1;
+ }
+ res = chdir(parent);
+ if (res == -1) {
+ eprintf(_("Failed to chdir to %s: %s\n"),
+ parent, strerror(errno));
+ return -1;
+ }
+ if (getcwd(buf, sizeof(buf)) == NULL) {
+ eprintf(_("Failed to obtain current directory: %s\n"),
+ strerror(errno));
+ return -1;
+ }
+ if (strcmp(buf, parent) != 0) {
+ eprintf(_("Mountpoint moved (%s -> %s)\n"),
+ parent, buf);
+ return -1;
+
+ }
+
+ return 0;
+}
+
+
+static int unmount_ncp(const char *mount_point)
+{
+ int currdir_fd = -1;
+ char *copy;
+ const char *last;
+ int res;
+
+ copy = strdup(mount_point);
+ if (copy == NULL) {
+ eprintf(_("Failed to allocate memory\n"));
+ return -1;
+ }
+ res = chdir_to_parent(copy, &last, &currdir_fd);
+ if (res == -1)
+ goto out;
+ res = check_is_mount(last, mount_point);
+ if (res == -1)
+ goto out;
+ res = ncp_mnt_umount(mount_point, last);
+
+out:
+ free(copy);
+ if (currdir_fd != -1) {
+ fchdir(currdir_fd);
+ close(currdir_fd);
+ }
+
+ return res;
+}
+
static int
do_umount(const char *mount_point)
{
int fid = open(mount_point, O_RDONLY, 0);
uid_t mount_uid;
+ int res;
if (fid == -1) {
eprintf(_("Could not open %s: %s\n"),
@@ -253,12 +441,8 @@ do_umount(const char *mount_point)
return -1;
}
close(fid);
- if (umount(mount_point) != 0) {
- eprintf(_("Could not umount %s: %s\n"),
- mount_point, strerror(errno));
- return -1;
- }
- return 0;
+ res = unmount_ncp(mount_point);
+ return res;
}
++++++ ncpfs-2_2_6_partial.patch ++++++
Index: ncpfs-2.2.6/sutil/ncplogin.c
===================================================================
--- ncpfs-2.2.6.orig/sutil/ncplogin.c
+++ ncpfs-2.2.6/sutil/ncplogin.c
@@ -934,7 +934,9 @@ ncpipx:;
NWDSFreeContext(ctx);
/* ncpmap, ncplogin must write in /etc/mtab */
{
+ block_sigs();
add_mnt_entry(mount_name, mount_point, info.flags);
+ unblock_sigs();
}
free(mount_name);
if (info.echo_mnt_pnt) {
Index: ncpfs-2.2.6/sutil/ncpm_common.c
===================================================================
--- ncpfs-2.2.6.orig/sutil/ncpm_common.c
+++ ncpfs-2.2.6/sutil/ncpm_common.c
@@ -360,7 +360,7 @@ void verify_argv(int argc, char* argv[])
#endif
static inline int ncpm_suser(void) {
- return setreuid(-1, 0);
+ return setresuid(0, 0, myuid);
}
static int ncpm_normal(void) {
@@ -368,11 +368,31 @@ static int ncpm_normal(void) {
int v;
e = errno;
- v = setreuid(-1, myuid);
+ v = setresuid(myuid, myuid, 0);
errno = e;
return v;
}
+void block_sigs(void) {
+
+ sigset_t mask, orig_mask;
+ sigfillset(&mask);
+
+ if(sigprocmask(SIG_SETMASK, &mask, &orig_mask) < 0) {
+ errexit(-1, _("Blocking signals failed.\n"));
+ }
+}
+
+void unblock_sigs(void) {
+
+ sigset_t mask, orig_mask;
+ sigemptyset(&mask);
+
+ if (sigprocmask(SIG_SETMASK, &mask, &orig_mask) < 0) {
+ errexit(-1, _("Un-blocking signals failed.\n"));
+ }
+}
+
static int proc_ncpm_mount(const char* source, const char* target, const char* filesystem, unsigned long mountflags, const void* data) {
int v;
int e;
Index: ncpfs-2.2.6/sutil/ncpm_common.h
===================================================================
--- ncpfs-2.2.6.orig/sutil/ncpm_common.h
+++ ncpfs-2.2.6/sutil/ncpm_common.h
@@ -121,6 +121,9 @@ int proc_buildconn(struct ncp_mount_info
int proc_aftermount(const struct ncp_mount_info* info, NWCONN_HANDLE* conn);
int proc_ncpm_umount(const char* dir);
+void block_sigs(void);
+void unblock_sigs(void);
+
#define UNUSED(x) x __attribute__((unused))
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
Index: ncpfs-2.2.6/sutil/ncpmount.c
===================================================================
--- ncpfs-2.2.6.orig/sutil/ncpmount.c
+++ ncpfs-2.2.6/sutil/ncpmount.c
@@ -720,7 +720,9 @@ ncpipx:;
ncp_close(conn);
if (!opt_n) {
+ block_sigs();
add_mnt_entry(mount_name, mount_point, info.flags);
+ unblock_sigs();
}
return 0;
}
Index: ncpfs-2.2.6/sutil/ncpumount.c
===================================================================
--- ncpfs-2.2.6.orig/sutil/ncpumount.c
+++ ncpfs-2.2.6/sutil/ncpumount.c
@@ -86,6 +86,8 @@
static char *progname;
static int is_ncplogout = 0;
+uid_t uid;
+
static void
usage(void)
{
@@ -126,6 +128,40 @@ static void eprintf(const char* message,
va_end(ap);
}
+/* Mostly copied from ncpm_common.c */
+void block_sigs(void) {
+
+ sigset_t mask, orig_mask;
+ sigfillset(&mask);
+ sigdelset(&mask, SIGALRM); /* Need SIGALRM for ncpumount */
+
+ if(setresuid(0, 0, uid) < 0) {
+ eprintf("Failed to raise privileges.\n");
+ exit(-1);
+ }
+
+ if(sigprocmask(SIG_SETMASK, &mask, &orig_mask) < 0) {
+ eprintf("Blocking signals failed.\n");
+ exit(-1);
+ }
+}
+
+void unblock_sigs(void) {
+
+ sigset_t mask, orig_mask;
+ sigemptyset(&mask);
+
+ if(setresuid(uid, uid, 0) < 0) {
+ eprintf("Failed to drop privileges.\n");
+ exit(-1);
+ }
+
+ if(sigprocmask(SIG_SETMASK, &mask, &orig_mask) < 0) {
+ eprintf("Un-blocking signals failed.\n");
+ exit(-1);
+ }
+}
+
static void alarmSignal(int sig) {
(void)sig;
}
@@ -201,10 +237,13 @@ static int clearMtab (const char* mount_
if (!numEntries)
return 0; /* don't waste time ! */
+ block_sigs();
+
while ((fd = open(MOUNTED "~", O_RDWR | O_CREAT | O_EXCL, 0600)) == -1) {
struct timespec tm;
if (errno != EEXIST || retries == 0) {
+ unblock_sigs();
eprintf(_("Can't get %s~ lock file: %s\n"), MOUNTED, strerror(errno));
return 1;
}
@@ -215,6 +254,7 @@ static int clearMtab (const char* mount_
alarm(0);
close(fd);
if (err) {
+ unblock_sigs();
eprintf(_("Can't lock lock file %s~: %s\n"), MOUNTED, _("Lock timed out"));
return 1;
}
@@ -232,9 +272,11 @@ static int clearMtab (const char* mount_
err = __clearMtab(mount_points, numEntries);
if ((unlink(MOUNTED "~") == -1) && (err == 0)){
+ unblock_sigs();
eprintf(_("Can't remove %s~"), MOUNTED);
return 1;
}
+ unblock_sigs();
return err;
}
@@ -422,13 +464,13 @@ do_umount(const char *mount_point)
int res;
if (fid == -1) {
- eprintf(_("Could not open %s: %s\n"),
- mount_point, strerror(errno));
+ eprintf(_("Invalid or unauthorized mountpoint %s\n"),
+ mount_point);
return -1;
}
if (ncp_get_mount_uid(fid, &mount_uid) != 0) {
close(fid);
- eprintf(_("%s probably not ncp-filesystem\n"),
+ eprintf(_("Invalid or unauthorized mountpoint %s\n"),
mount_point);
return -1;
}
@@ -591,7 +633,8 @@ main(int argc, char *argv[])
int allConns = 0;
const char *serverName = NULL;
const char *treeName = NULL;
- uid_t uid = getuid();
+
+ uid = getuid();
progname = strrchr(argv[0], '/');
if (progname) {
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Remember to have fun...
--
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org