~ubuntu-branches/ubuntu/jaunty/fuse/jaunty-security

« back to all changes in this revision

Viewing changes to lib/mount_util.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2008-01-29 10:38:39 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20080129103839-kmz63d04pnttuuoc
Tags: 2.7.2-1ubuntu1
* Resynchronise with Debian. Remaining changes:
  - Don't install the init script; install the udev rule and the module
    configuration file instead.
  - debian/45-fuse.rules: set /dev/fuse group to fuse.
  - debian/fuse-utils.modprobe: module configuration file that mounts the
    control filesystem when fuse is loaded and unmounts it when fuse is
    unloaded, along with checking that the control FS is mounting before
    unmounting it.
  - debian/fuse-utils.install: add the udev rule, the module configuration
    file, and ulockmgr_server.
  - Load fuse on install, and set it so it gets loaded on reboot.
  - Move fusermount and ulockmgr_server to /bin and associated libraries
    to /lib.
  - Create libfuse2-udeb and fuse-utils-udeb.
  - Copy /sbin/mount.fuse and the fuse kernel module into the initramfs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
    FUSE: Filesystem in Userspace
3
 
    Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
 
2
  FUSE: Filesystem in Userspace
 
3
  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
4
4
 
5
 
    This program can be distributed under the terms of the GNU LGPLv2.
6
 
    See the file COPYING.LIB.
 
5
  This program can be distributed under the terms of the GNU LGPLv2.
 
6
  See the file COPYING.LIB.
7
7
*/
8
8
 
9
9
#include "mount_util.h"
17
17
#include <mntent.h>
18
18
#include <sys/stat.h>
19
19
#include <sys/wait.h>
 
20
#include <sys/mount.h>
20
21
 
21
22
static int mtab_needs_update(const char *mnt)
22
23
{
23
 
    struct stat stbuf;
24
 
 
25
 
    /* If mtab is within new mount, don't touch it */
26
 
    if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
27
 
        _PATH_MOUNTED[strlen(mnt)] == '/')
28
 
        return 0;
29
 
 
30
 
    if (lstat(_PATH_MOUNTED, &stbuf) != -1 && S_ISLNK(stbuf.st_mode))
31
 
        return 0;
32
 
 
33
 
    return 1;
 
24
        struct stat stbuf;
 
25
 
 
26
        /* If mtab is within new mount, don't touch it */
 
27
        if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
 
28
            _PATH_MOUNTED[strlen(mnt)] == '/')
 
29
                return 0;
 
30
 
 
31
        if (lstat(_PATH_MOUNTED, &stbuf) != -1 && S_ISLNK(stbuf.st_mode))
 
32
                return 0;
 
33
 
 
34
        return 1;
34
35
}
35
36
 
36
37
int fuse_mnt_add_mount(const char *progname, const char *fsname,
37
 
                       const char *mnt, const char *type, const char *opts)
 
38
                       const char *mnt, const char *type, const char *opts)
38
39
{
39
 
    int res;
40
 
    int status;
41
 
 
42
 
    if (!mtab_needs_update(mnt))
43
 
        return 0;
44
 
 
45
 
    res = fork();
46
 
    if (res == -1) {
47
 
        fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
48
 
        return -1;
49
 
    }
50
 
    if (res == 0) {
51
 
        char templ[] = "/tmp/fusermountXXXXXX";
52
 
        char *tmp;
53
 
 
54
 
        setuid(geteuid());
55
 
 
56
 
        /* 
57
 
         * hide in a directory, where mount isn't able to resolve
58
 
         * fsname as a valid path
59
 
         */
60
 
        tmp = mkdtemp(templ);
61
 
        if (!tmp) {
62
 
            fprintf(stderr, "%s: failed to create temporary directory\n",
63
 
                    progname);
64
 
            exit(1);
65
 
        }
66
 
        if (chdir(tmp)) {
67
 
            fprintf(stderr, "%s: failed to chdir to %s: %s\n",
68
 
                    progname, tmp, strerror(errno));
69
 
            exit(1);
70
 
        }
71
 
        rmdir(tmp);
72
 
        execl("/bin/mount", "/bin/mount", "-i", "-f", "-t", type, "-o", opts,
73
 
              fsname, mnt, NULL);
74
 
        fprintf(stderr, "%s: failed to execute /bin/mount: %s\n", progname,
75
 
                strerror(errno));
76
 
        exit(1);
77
 
    }
78
 
    res = waitpid(res, &status, 0);
79
 
    if (res == -1) {
80
 
        fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
81
 
        return -1;
82
 
    }
83
 
    if (status != 0)
84
 
        return -1;
85
 
 
86
 
    return 0;
 
40
        int res;
 
41
        int status;
 
42
 
 
43
        if (!mtab_needs_update(mnt))
 
44
                return 0;
 
45
 
 
46
        res = fork();
 
47
        if (res == -1) {
 
48
                fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
 
49
                return -1;
 
50
        }
 
51
        if (res == 0) {
 
52
                char templ[] = "/tmp/fusermountXXXXXX";
 
53
                char *tmp;
 
54
 
 
55
                setuid(geteuid());
 
56
 
 
57
                /*
 
58
                 * hide in a directory, where mount isn't able to resolve
 
59
                 * fsname as a valid path
 
60
                 */
 
61
                tmp = mkdtemp(templ);
 
62
                if (!tmp) {
 
63
                        fprintf(stderr,
 
64
                                "%s: failed to create temporary directory\n",
 
65
                                progname);
 
66
                        exit(1);
 
67
                }
 
68
                if (chdir(tmp)) {
 
69
                        fprintf(stderr, "%s: failed to chdir to %s: %s\n",
 
70
                                progname, tmp, strerror(errno));
 
71
                        exit(1);
 
72
                }
 
73
                rmdir(tmp);
 
74
                execl("/bin/mount", "/bin/mount", "-i", "-f", "-t", type,
 
75
                      "-o", opts, fsname, mnt, NULL);
 
76
                fprintf(stderr, "%s: failed to execute /bin/mount: %s\n",
 
77
                        progname, strerror(errno));
 
78
                exit(1);
 
79
        }
 
80
        res = waitpid(res, &status, 0);
 
81
        if (res == -1) {
 
82
                fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
 
83
                return -1;
 
84
        }
 
85
        if (status != 0)
 
86
                return -1;
 
87
 
 
88
        return 0;
87
89
}
88
90
 
89
91
int fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
90
92
{
91
 
    int res;
92
 
    int status;
93
 
 
94
 
    if (!mtab_needs_update(mnt))
95
 
        return 0;
96
 
 
97
 
    res = fork();
98
 
    if (res == -1) {
99
 
        fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
100
 
        return -1;
101
 
    }
102
 
    if (res == 0) {
103
 
        setuid(geteuid());
104
 
        execl("/bin/umount", "/bin/umount", "-i", mnt, lazy ? "-l" : NULL,
105
 
              NULL);
106
 
        fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", progname,
107
 
                strerror(errno));
108
 
        exit(1);
109
 
    }
110
 
    res = waitpid(res, &status, 0);
111
 
    if (res == -1) {
112
 
        fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
113
 
        return -1;
114
 
    }
115
 
    if (status != 0)
116
 
        return -1;
117
 
 
118
 
    return 0;
 
93
        int res;
 
94
        int status;
 
95
 
 
96
        if (!mtab_needs_update(mnt)) {
 
97
                res = umount2(mnt, lazy ? 2 : 0);
 
98
                if (res == -1)
 
99
                        fprintf(stderr, "%s: failed to unmount %s: %s\n",
 
100
                                progname, mnt, strerror(errno));
 
101
                return res;
 
102
        }
 
103
 
 
104
        res = fork();
 
105
        if (res == -1) {
 
106
                fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
 
107
                return -1;
 
108
        }
 
109
        if (res == 0) {
 
110
                setuid(geteuid());
 
111
                execl("/bin/umount", "/bin/umount", "-i", mnt,
 
112
                      lazy ? "-l" : NULL, NULL);
 
113
                fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
 
114
                        progname, strerror(errno));
 
115
                exit(1);
 
116
        }
 
117
        res = waitpid(res, &status, 0);
 
118
        if (res == -1) {
 
119
                fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
 
120
                return -1;
 
121
        }
 
122
        if (status != 0)
 
123
                return -1;
 
124
 
 
125
        return 0;
119
126
}
120
127
 
121
128
char *fuse_mnt_resolve_path(const char *progname, const char *orig)
122
129
{
123
 
    char buf[PATH_MAX];
124
 
    char *copy;
125
 
    char *dst;
126
 
    char *end;
127
 
    char *lastcomp;
128
 
    const char *toresolv;
129
 
 
130
 
    if (!orig[0]) {
131
 
        fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
132
 
        return NULL;
133
 
    }
134
 
 
135
 
    copy = strdup(orig);
136
 
    if (copy == NULL) {
137
 
        fprintf(stderr, "%s: failed to allocate memory\n", progname);
138
 
        return NULL;
139
 
    }
140
 
 
141
 
    toresolv = copy;
142
 
    lastcomp = NULL;
143
 
    for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
144
 
    if (end[0] != '/') {
145
 
        char *tmp;
146
 
        end[1] = '\0';
147
 
        tmp = strrchr(copy, '/');
148
 
        if (tmp == NULL) {
149
 
            lastcomp = copy;
150
 
            toresolv = ".";
151
 
        } else {
152
 
            lastcomp = tmp + 1;
153
 
            if (tmp == copy)
154
 
                toresolv = "/";
155
 
        }
156
 
        if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
157
 
            lastcomp = NULL;
158
 
            toresolv = copy;
159
 
        }
160
 
        else if (tmp)
161
 
            tmp[0] = '\0';
162
 
    }
163
 
    if (realpath(toresolv, buf) == NULL) {
164
 
        fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
165
 
                strerror(errno));
166
 
        free(copy);
167
 
        return NULL;
168
 
    }
169
 
    if (lastcomp == NULL)
170
 
        dst = strdup(buf);
171
 
    else {
172
 
        dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
173
 
        if (dst) {
174
 
            unsigned buflen = strlen(buf);
175
 
            if (buflen && buf[buflen-1] == '/')
176
 
                sprintf(dst, "%s%s", buf, lastcomp);
177
 
            else
178
 
                sprintf(dst, "%s/%s", buf, lastcomp);
179
 
        }
180
 
    }
181
 
    free(copy);
182
 
    if (dst == NULL)
183
 
        fprintf(stderr, "%s: failed to allocate memory\n", progname);
184
 
    return dst;
 
130
        char buf[PATH_MAX];
 
131
        char *copy;
 
132
        char *dst;
 
133
        char *end;
 
134
        char *lastcomp;
 
135
        const char *toresolv;
 
136
 
 
137
        if (!orig[0]) {
 
138
                fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname,
 
139
                        orig);
 
140
                return NULL;
 
141
        }
 
142
 
 
143
        copy = strdup(orig);
 
144
        if (copy == NULL) {
 
145
                fprintf(stderr, "%s: failed to allocate memory\n", progname);
 
146
                return NULL;
 
147
        }
 
148
 
 
149
        toresolv = copy;
 
150
        lastcomp = NULL;
 
151
        for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
 
152
        if (end[0] != '/') {
 
153
                char *tmp;
 
154
                end[1] = '\0';
 
155
                tmp = strrchr(copy, '/');
 
156
                if (tmp == NULL) {
 
157
                        lastcomp = copy;
 
158
                        toresolv = ".";
 
159
                } else {
 
160
                        lastcomp = tmp + 1;
 
161
                        if (tmp == copy)
 
162
                                toresolv = "/";
 
163
                }
 
164
                if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
 
165
                        lastcomp = NULL;
 
166
                        toresolv = copy;
 
167
                }
 
168
                else if (tmp)
 
169
                        tmp[0] = '\0';
 
170
        }
 
171
        if (realpath(toresolv, buf) == NULL) {
 
172
                fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
 
173
                        strerror(errno));
 
174
                free(copy);
 
175
                return NULL;
 
176
        }
 
177
        if (lastcomp == NULL)
 
178
                dst = strdup(buf);
 
179
        else {
 
180
                dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
 
181
                if (dst) {
 
182
                        unsigned buflen = strlen(buf);
 
183
                        if (buflen && buf[buflen-1] == '/')
 
184
                                sprintf(dst, "%s%s", buf, lastcomp);
 
185
                        else
 
186
                                sprintf(dst, "%s/%s", buf, lastcomp);
 
187
                }
 
188
        }
 
189
        free(copy);
 
190
        if (dst == NULL)
 
191
                fprintf(stderr, "%s: failed to allocate memory\n", progname);
 
192
        return dst;
185
193
}
186
194
 
187
195
int fuse_mnt_check_empty(const char *progname, const char *mnt,
188
 
                         mode_t rootmode, off_t rootsize)
 
196
                         mode_t rootmode, off_t rootsize)
189
197
{
190
 
    int isempty = 1;
191
 
 
192
 
    if (S_ISDIR(rootmode)) {
193
 
        struct dirent *ent;
194
 
        DIR *dp = opendir(mnt);
195
 
        if (dp == NULL) {
196
 
            fprintf(stderr, "%s: failed to open mountpoint for reading: %s\n",
197
 
                    progname, strerror(errno));
198
 
            return -1;
199
 
        }
200
 
        while ((ent = readdir(dp)) != NULL) {
201
 
            if (strcmp(ent->d_name, ".") != 0 &&
202
 
                strcmp(ent->d_name, "..") != 0) {
203
 
                isempty = 0;
204
 
                break;
205
 
            }
206
 
        }
207
 
        closedir(dp);
208
 
    } else if (rootsize)
209
 
        isempty = 0;
210
 
 
211
 
    if (!isempty) {
212
 
        fprintf(stderr, "%s: mountpoint is not empty\n", progname);
213
 
        fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
214
 
        return -1;
215
 
    }
216
 
    return 0;
 
198
        int isempty = 1;
 
199
 
 
200
        if (S_ISDIR(rootmode)) {
 
201
                struct dirent *ent;
 
202
                DIR *dp = opendir(mnt);
 
203
                if (dp == NULL) {
 
204
                        fprintf(stderr,
 
205
                                "%s: failed to open mountpoint for reading: %s\n",
 
206
                                progname, strerror(errno));
 
207
                        return -1;
 
208
                }
 
209
                while ((ent = readdir(dp)) != NULL) {
 
210
                        if (strcmp(ent->d_name, ".") != 0 &&
 
211
                            strcmp(ent->d_name, "..") != 0) {
 
212
                                isempty = 0;
 
213
                                break;
 
214
                        }
 
215
                }
 
216
                closedir(dp);
 
217
        } else if (rootsize)
 
218
                isempty = 0;
 
219
 
 
220
        if (!isempty) {
 
221
                fprintf(stderr, "%s: mountpoint is not empty\n", progname);
 
222
                fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
 
223
                return -1;
 
224
        }
 
225
        return 0;
217
226
}
218
227
 
219
228
int fuse_mnt_check_fuseblk(void)
220
229
{
221
 
    char buf[256];
222
 
    FILE *f = fopen("/proc/filesystems", "r");
223
 
    if (!f)
224
 
        return 1;
225
 
 
226
 
    while (fgets(buf, sizeof(buf), f))
227
 
        if (strstr(buf, "fuseblk\n")) {
228
 
            fclose(f);
229
 
            return 1;
230
 
        }
231
 
 
232
 
    fclose(f);
233
 
    return 0;
 
230
        char buf[256];
 
231
        FILE *f = fopen("/proc/filesystems", "r");
 
232
        if (!f)
 
233
                return 1;
 
234
 
 
235
        while (fgets(buf, sizeof(buf), f))
 
236
                if (strstr(buf, "fuseblk\n")) {
 
237
                        fclose(f);
 
238
                        return 1;
 
239
                }
 
240
 
 
241
        fclose(f);
 
242
        return 0;
234
243
}