Bug Summary

File:xlators/mount/fuse/src/../../../../contrib/fuse-lib/mount-common.c
Location:line 248, column 17
Description:The return value from the call to 'setuid' is not checked. If an error occurs in 'setuid', the following code may execute with unexpected privileges

Annotated Source Code

1/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4 Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
5
6 This program can be distributed under the terms of the GNU LGPLv2.
7 See the file COPYING.LIB.
8*/
9
10#include "mount-gluster-compat.h"
11
12/*
13 * These functions (and gf_fuse_umount() in mount.c)
14 * were originally taken from libfuse as of commit 7960e99e
15 * (http://fuse.git.sourceforge.net/git/gitweb.cgi?p=fuse/fuse;a=commit;h=7960e99e)
16 * almost verbatim. What has been changed upon adoption:
17 * - style adopted to that of glusterfs
18 * - s/fprintf/gf_log/
19 * - s/free/FREE/, s/malloc/MALLOC/
20 * - there are some other minor things
21 *
22 * For changes that were made later and syncs with upstream,
23 * see the commit log and per-function comments.
24 */
25
26#ifndef __NetBSD__
27/* FUSE: cherry-picked bd99f9cf */
28static int
29mtab_needs_update (const char *mnt)
30{
31 int res;
32 struct stat stbuf;
33
34 /* If mtab is within new mount, don't touch it */
35 if (strncmp (mnt, _PATH_MOUNTED"/etc/mtab", strlen (mnt)) == 0 &&
36 _PATH_MOUNTED"/etc/mtab"[strlen (mnt)] == '/')
37 return 0;
38
39 /*
40 * Skip mtab update if /etc/mtab:
41 *
42 * - doesn't exist,
43 * - is a symlink,
44 * - is on a read-only filesystem.
45 */
46 res = lstat (_PATH_MOUNTED"/etc/mtab", &stbuf);
47 if (res == -1) {
48 if (errno(*__errno_location ()) == ENOENT2)
49 return 0;
50 } else {
51 uid_t ruid;
52 int err;
53
54 if (S_ISLNK (stbuf.st_mode)((((stbuf.st_mode)) & 0170000) == (0120000)))
55 return 0;
56
57 ruid = getuid ();
58 if (ruid != 0)
59 setreuid (0, -1);
60
61 res = access (_PATH_MOUNTED"/etc/mtab", W_OK2);
62 err = (res == -1) ? errno(*__errno_location ()) : 0;
63 if (ruid != 0)
64 setreuid (ruid, -1);
65
66 if (err == EROFS30)
67 return 0;
68 }
69
70 return 1;
71}
72#else /* __NetBSD__ */
73#define mtab_needs_update(x) 1
74#endif /* __NetBSD__ */
75
76/* FUSE: called add_mount_legacy(); R.I.P. as of cbd3a2a8 */
77int
78fuse_mnt_add_mount (const char *progname, const char *fsname,
79 const char *mnt, const char *type, const char *opts)
80{
81 int res;
82 int status;
83 sigset_t blockmask;
84 sigset_t oldmask;
85
86 if (!mtab_needs_update (mnt))
87 return 0;
88
89 sigemptyset (&blockmask);
90 sigaddset (&blockmask, SIGCHLD17);
91 res = sigprocmask (SIG_BLOCK0, &blockmask, &oldmask);
92 if (res == -1) {
93 GFFUSE_LOGERR ("%s: sigprocmask: %s",do { do { if (0) printf ("%s: sigprocmask: %s", progname, strerror
((*__errno_location ()))); } while (0); _gf_log ("glusterfs-fuse"
, "../../../../contrib/fuse-lib/mount-common.c", __FUNCTION__
, 94, GF_LOG_ERROR,"%s: sigprocmask: %s", progname, strerror (
(*__errno_location ()))); } while (0)
94 progname, strerror (errno))do { do { if (0) printf ("%s: sigprocmask: %s", progname, strerror
((*__errno_location ()))); } while (0); _gf_log ("glusterfs-fuse"
, "../../../../contrib/fuse-lib/mount-common.c", __FUNCTION__
, 94, GF_LOG_ERROR,"%s: sigprocmask: %s", progname, strerror (
(*__errno_location ()))); } while (0)
;
95 return -1;
96 }
97
98 res = fork ();
99 if (res == -1) {
100 GFFUSE_LOGERR ("%s: fork: %s", progname, strerror (errno))do { do { if (0) printf ("%s: fork: %s", progname, strerror (
(*__errno_location ()))); } while (0); _gf_log ("glusterfs-fuse"
, "../../../../contrib/fuse-lib/mount-common.c", __FUNCTION__
, 100, GF_LOG_ERROR,"%s: fork: %s", progname, strerror ((*__errno_location
()))); } while (0)
;
101 goto out_restore;
102 }
103 if (res == 0) {
104 char templ[] = "/tmp/fusermountXXXXXX";
105 char *tmp;
106
107 sigprocmask (SIG_SETMASK2, &oldmask, NULL((void*)0));
108 setuid (geteuid ());
109
110 /*
111 * hide in a directory, where mount isn't able to resolve
112 * fsname as a valid path
113 */
114 tmp = mkdtemp (templ);
115 if (!tmp) {
116 GFFUSE_LOGERR ("%s: failed to create temporary directory",do { do { if (0) printf ("%s: failed to create temporary directory"
, progname); } while (0); _gf_log ("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 117, GF_LOG_ERROR,"%s: failed to create temporary directory"
, progname); } while (0)
117 progname)do { do { if (0) printf ("%s: failed to create temporary directory"
, progname); } while (0); _gf_log ("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 117, GF_LOG_ERROR,"%s: failed to create temporary directory"
, progname); } while (0)
;
118 exit (1);
119 }
120 if (chdir (tmp)) {
121 GFFUSE_LOGERR ("%s: failed to chdir to %s: %s",do { do { if (0) printf ("%s: failed to chdir to %s: %s", progname
, tmp, strerror ((*__errno_location ()))); } while (0); _gf_log
("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 122, GF_LOG_ERROR,"%s: failed to chdir to %s: %s"
, progname, tmp, strerror ((*__errno_location ()))); } while (
0)
122 progname, tmp, strerror (errno))do { do { if (0) printf ("%s: failed to chdir to %s: %s", progname
, tmp, strerror ((*__errno_location ()))); } while (0); _gf_log
("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 122, GF_LOG_ERROR,"%s: failed to chdir to %s: %s"
, progname, tmp, strerror ((*__errno_location ()))); } while (
0)
;
123 exit (1);
124 }
125 rmdir (tmp);
126 execl (_PATH_MOUNT"/bin/mount", _PATH_MOUNT"/bin/mount", "-i", "-f", "-t", type,
127 "-o", opts, fsname, mnt, NULL((void*)0));
128 GFFUSE_LOGERR ("%s: failed to execute %s: %s",do { do { if (0) printf ("%s: failed to execute %s: %s", progname
, "/bin/mount", strerror ((*__errno_location ()))); } while (
0); _gf_log ("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 129, GF_LOG_ERROR,"%s: failed to execute %s: %s"
, progname, "/bin/mount", strerror ((*__errno_location ())));
} while (0)
129 progname, _PATH_MOUNT, strerror (errno))do { do { if (0) printf ("%s: failed to execute %s: %s", progname
, "/bin/mount", strerror ((*__errno_location ()))); } while (
0); _gf_log ("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 129, GF_LOG_ERROR,"%s: failed to execute %s: %s"
, progname, "/bin/mount", strerror ((*__errno_location ())));
} while (0)
;
130 exit (1);
131 }
132
133 res = waitpid (res, &status, 0);
134 if (res == -1)
135 GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno))do { do { if (0) printf ("%s: waitpid: %s", progname, strerror
((*__errno_location ()))); } while (0); _gf_log ("glusterfs-fuse"
, "../../../../contrib/fuse-lib/mount-common.c", __FUNCTION__
, 135, GF_LOG_ERROR,"%s: waitpid: %s", progname, strerror ((*
__errno_location ()))); } while (0)
;
136 res = (res != -1 && status == 0) ? 0 : -1;
137
138 out_restore:
139 sigprocmask (SIG_SETMASK2, &oldmask, NULL((void*)0));
140 return res;
141}
142
143char *
144fuse_mnt_resolve_path (const char *progname, const char *orig)
145{
146 char buf[PATH_MAX4096];
147 char *copy;
148 char *dst;
149 char *end;
150 char *lastcomp;
151 const char *toresolv;
152
153 if (!orig[0]) {
154 GFFUSE_LOGERR ("%s: invalid mountpoint '%s'", progname, orig)do { do { if (0) printf ("%s: invalid mountpoint '%s'", progname
, orig); } while (0); _gf_log ("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 154, GF_LOG_ERROR,"%s: invalid mountpoint '%s'"
, progname, orig); } while (0)
;
155 return NULL((void*)0);
156 }
157
158 copy = strdup (orig);
159 if (copy == NULL((void*)0)) {
160 GFFUSE_LOGERR ("%s: failed to allocate memory", progname)do { do { if (0) printf ("%s: failed to allocate memory", progname
); } while (0); _gf_log ("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 160, GF_LOG_ERROR,"%s: failed to allocate memory"
, progname); } while (0)
;
161 return NULL((void*)0);
162 }
163
164 toresolv = copy;
165 lastcomp = NULL((void*)0);
166 for (end = copy + strlen (copy) - 1; end > copy && *end == '/'; end --);
167 if (end[0] != '/') {
168 char *tmp;
169 end[1] = '\0';
170 tmp = strrchr (copy, '/');
171 if (tmp == NULL((void*)0)) {
172 lastcomp = copy;
173 toresolv = ".";
174 } else {
175 lastcomp = tmp + 1;
176 if (tmp == copy)
177 toresolv = "/";
178 }
179 if (strcmp (lastcomp, ".") == 0 || strcmp (lastcomp, "..") == 0) {
180 lastcomp = NULL((void*)0);
181 toresolv = copy;
182 }
183 else if (tmp)
184 tmp[0] = '\0';
185 }
186 if (realpath (toresolv, buf) == NULL((void*)0)) {
187 GFFUSE_LOGERR ("%s: bad mount point %s: %s", progname, orig,do { do { if (0) printf ("%s: bad mount point %s: %s", progname
, orig, strerror ((*__errno_location ()))); } while (0); _gf_log
("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 188, GF_LOG_ERROR,"%s: bad mount point %s: %s"
, progname, orig, strerror ((*__errno_location ()))); } while
(0)
188 strerror (errno))do { do { if (0) printf ("%s: bad mount point %s: %s", progname
, orig, strerror ((*__errno_location ()))); } while (0); _gf_log
("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 188, GF_LOG_ERROR,"%s: bad mount point %s: %s"
, progname, orig, strerror ((*__errno_location ()))); } while
(0)
;
189 FREE (copy)if (copy != ((void*)0)) { free ((void *)copy); copy = (void *
)0xeeeeeeee; }
;
190 return NULL((void*)0);
191 }
192 if (lastcomp == NULL((void*)0))
193 dst = strdup (buf);
194 else {
195 dst = (char *) MALLOC (strlen (buf) + 1 + strlen (lastcomp) + 1)__gf_default_malloc(strlen (buf) + 1 + strlen (lastcomp) + 1);
196 if (dst) {
197 unsigned buflen = strlen (buf);
198 if (buflen && buf[buflen-1] == '/')
199 sprintf (dst, "%s%s", buf, lastcomp);
200 else
201 sprintf (dst, "%s/%s", buf, lastcomp);
202 }
203 }
204 FREE (copy)if (copy != ((void*)0)) { free ((void *)copy); copy = (void *
)0xeeeeeeee; }
;
205 if (dst == NULL((void*)0))
206 GFFUSE_LOGERR ("%s: failed to allocate memory", progname)do { do { if (0) printf ("%s: failed to allocate memory", progname
); } while (0); _gf_log ("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 206, GF_LOG_ERROR,"%s: failed to allocate memory"
, progname); } while (0)
;
207 return dst;
208}
209
210/* FUSE: to support some changes that were reverted since
211 * then, it was split in two (fuse_mnt_umount() and
212 * exec_umount()); however the actual code is same as here
213 * since 0197ce40
214 */
215int
216fuse_mnt_umount (const char *progname, const char *abs_mnt,
217 const char *rel_mnt, int lazy)
218{
219 int res;
220 int status;
221 sigset_t blockmask;
222 sigset_t oldmask;
223
224 if (!mtab_needs_update (abs_mnt)) {
225 res = umount2 (rel_mnt, lazy ? 2 : 0);
226 if (res == -1)
227 GFFUSE_LOGERR ("%s: failed to unmount %s: %s",do { do { if (0) printf ("%s: failed to unmount %s: %s", progname
, abs_mnt, strerror ((*__errno_location ()))); } while (0); _gf_log
("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 228, GF_LOG_ERROR,"%s: failed to unmount %s: %s"
, progname, abs_mnt, strerror ((*__errno_location ()))); } while
(0)
228 progname, abs_mnt, strerror (errno))do { do { if (0) printf ("%s: failed to unmount %s: %s", progname
, abs_mnt, strerror ((*__errno_location ()))); } while (0); _gf_log
("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 228, GF_LOG_ERROR,"%s: failed to unmount %s: %s"
, progname, abs_mnt, strerror ((*__errno_location ()))); } while
(0)
;
229 return res;
230 }
231
232 sigemptyset (&blockmask);
233 sigaddset (&blockmask, SIGCHLD17);
234 res = sigprocmask (SIG_BLOCK0, &blockmask, &oldmask);
235 if (res == -1) {
236 GFFUSE_LOGERR ("%s: sigprocmask: %s", progname,do { do { if (0) printf ("%s: sigprocmask: %s", progname, strerror
((*__errno_location ()))); } while (0); _gf_log ("glusterfs-fuse"
, "../../../../contrib/fuse-lib/mount-common.c", __FUNCTION__
, 237, GF_LOG_ERROR,"%s: sigprocmask: %s", progname, strerror
((*__errno_location ()))); } while (0)
237 strerror (errno))do { do { if (0) printf ("%s: sigprocmask: %s", progname, strerror
((*__errno_location ()))); } while (0); _gf_log ("glusterfs-fuse"
, "../../../../contrib/fuse-lib/mount-common.c", __FUNCTION__
, 237, GF_LOG_ERROR,"%s: sigprocmask: %s", progname, strerror
((*__errno_location ()))); } while (0)
;
238 return -1;
239 }
240
241 res = fork ();
242 if (res == -1) {
243 GFFUSE_LOGERR ("%s: fork: %s", progname, strerror (errno))do { do { if (0) printf ("%s: fork: %s", progname, strerror (
(*__errno_location ()))); } while (0); _gf_log ("glusterfs-fuse"
, "../../../../contrib/fuse-lib/mount-common.c", __FUNCTION__
, 243, GF_LOG_ERROR,"%s: fork: %s", progname, strerror ((*__errno_location
()))); } while (0)
;
244 goto out_restore;
245 }
246 if (res == 0) {
247 sigprocmask (SIG_SETMASK2, &oldmask, NULL((void*)0));
248 setuid (geteuid ());
The return value from the call to 'setuid' is not checked. If an error occurs in 'setuid', the following code may execute with unexpected privileges
249 execl ("/bin/umount", "/bin/umount", "-i", rel_mnt,
250 lazy ? "-l" : NULL((void*)0), NULL((void*)0));
251 GFFUSE_LOGERR ("%s: failed to execute /bin/umount: %s",do { do { if (0) printf ("%s: failed to execute /bin/umount: %s"
, progname, strerror ((*__errno_location ()))); } while (0); _gf_log
("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 252, GF_LOG_ERROR,"%s: failed to execute /bin/umount: %s"
, progname, strerror ((*__errno_location ()))); } while (0)
252 progname, strerror (errno))do { do { if (0) printf ("%s: failed to execute /bin/umount: %s"
, progname, strerror ((*__errno_location ()))); } while (0); _gf_log
("glusterfs-fuse", "../../../../contrib/fuse-lib/mount-common.c"
, __FUNCTION__, 252, GF_LOG_ERROR,"%s: failed to execute /bin/umount: %s"
, progname, strerror ((*__errno_location ()))); } while (0)
;
253 exit (1);
254 }
255 res = waitpid (res, &status, 0);
256 if (res == -1)
257 GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno))do { do { if (0) printf ("%s: waitpid: %s", progname, strerror
((*__errno_location ()))); } while (0); _gf_log ("glusterfs-fuse"
, "../../../../contrib/fuse-lib/mount-common.c", __FUNCTION__
, 257, GF_LOG_ERROR,"%s: waitpid: %s", progname, strerror ((*
__errno_location ()))); } while (0)
;
258
259 if (status != 0)
260 res = -1;
261
262 out_restore:
263 sigprocmask (SIG_SETMASK2, &oldmask, NULL((void*)0));
264 return res;
265}