~ubuntu-branches/ubuntu/lucid/samba/lucid-security

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
Description: fix denial of service via stale mtab lockfile
Origin: backport, http://git.samba.org/?p=cifs-utils.git;a=commitdiff;h=810f7e4e0f2dbcbee0294d9b371071cb08268200

Index: samba-3.4.7~dfsg/source3/client/mount.cifs.c
===================================================================
--- samba-3.4.7~dfsg.orig/source3/client/mount.cifs.c	2011-09-29 09:21:45.361326382 -0400
+++ samba-3.4.7~dfsg/source3/client/mount.cifs.c	2011-09-29 09:25:33.893332232 -0400
@@ -40,6 +40,7 @@
 #include <fcntl.h>
 #include <limits.h>
 #include "mount.h"
+#include <signal.h>
 
 #define MOUNT_CIFS_VERSION_MAJOR "1"
 #define MOUNT_CIFS_VERSION_MINOR "12"
@@ -182,9 +183,9 @@
 }
 
 /* caller frees username if necessary */
-static char * getusername(void) {
+static char * getusername(uid_t uid) {
 	char *username = NULL;
-	struct passwd *password = getpwuid(getuid());
+	struct passwd *password = getpwuid(uid);
 
 	if (password) {
 		username = password->pw_name;
@@ -1082,6 +1083,7 @@
 	const char * ipaddr = NULL;
 	char * uuid = NULL;
 	char * mountpoint = NULL;
+	char * mount_user = NULL;
 	char * options = NULL;
 	char * optionstail;
 	char * resolved_path = NULL;
@@ -1105,6 +1107,7 @@
 	struct sockaddr_in *addr4;
 	struct sockaddr_in6 *addr6;
 	FILE * pmntfile;
+	sigset_t mask, oldmask;
 
 	/* setlocale(LC_ALL, "");
 	bindtextdomain(PACKAGE, LOCALEDIR);
@@ -1367,7 +1370,7 @@
 		if (getenv("USER"))
 			user_name = strdup(getenv("USER"));
 		if (user_name == NULL)
-			user_name = getusername();
+			user_name = getusername(getuid());
 		got_user = 1;
 	}
        
@@ -1530,6 +1533,38 @@
 
 	if (nomtab)
 		goto mount_exit;
+
+	uid = getuid();
+	if (uid != 0)
+		mount_user = getusername(uid);
+
+	/*
+	 * Set the real uid to the effective uid. This prevents unprivileged
+	 * users from sending signals to this process, though ^c on controlling
+	 * terminal should still work.
+	 */
+	rc = setreuid(geteuid(), -1);
+	if (rc != 0) {
+		fprintf(stderr, "Unable to set real uid to effective uid: %s\n",
+				strerror(errno));
+		rc = EX_FILEIO;
+		goto mount_exit;
+	}
+
+	rc = sigfillset(&mask);
+	if (rc) {
+		fprintf(stderr, "Unable to set filled signal mask\n");
+		rc = EX_FILEIO;
+		goto mount_exit;
+	}
+
+	rc = sigprocmask(SIG_SETMASK, &mask, &oldmask);
+	if (rc) {
+		fprintf(stderr, "Unable to make process ignore signals\n");
+		rc = EX_FILEIO;
+		goto mount_exit;
+	}
+
 	atexit(unlock_mtab);
 	rc = lock_mtab();
 	if (rc) {
@@ -1548,7 +1583,6 @@
 	mountent.mnt_type = CONST_DISCARD(char *,"cifs");
 	mountent.mnt_opts = (char *)malloc(220);
 	if(mountent.mnt_opts) {
-		char * mount_user = getusername();
 		memset(mountent.mnt_opts,0,200);
 		if(flags & MS_RDONLY)
 			strlcat(mountent.mnt_opts,"ro",220);
@@ -1581,6 +1615,7 @@
 	SAFE_FREE(mountent.mnt_opts);
 	if (rc)
 		rc = EX_FILEIO;
+	sigprocmask(SIG_SETMASK, &oldmask, NULL);
 mount_exit:
 	if(mountpassword) {
 		int len = strlen(mountpassword);