~ubuntu-branches/ubuntu/trusty/mountall/trusty-proposed

« back to all changes in this revision

Viewing changes to src/mountall.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant, Scott James Remnant, Kees Cook
  • Date: 2009-09-23 14:19:01 UTC
  • Revision ID: james.westby@ubuntu.com-20090923141901-anla1vw4troxeixl
Tags: 0.1.8
[ Scott James Remnant ]
* Further work on the fix from the previous version where the root
  filesystem would always be considered "local", retain that from the
  POV of the {virtual,local,remote}-filesystems events, but do mount
  the root straight away when it's virtual since there's no device to
  wait until it's ready.  LP: #431204.
* If a remote filesystem is already mounted and doesn't need a remount,
  don't wait for a network device to come up.  LP: #430348.

* Ignore single and double quotes in fstab device specifications, since
  mount -a used to.  LP: #431064.
* Never write mtab when mounting a mount with showthroughs (ie. /var)
  and instead update mtab once we've moved it into place
  later.  LP: #434172.

[ Kees Cook ]
* src/mountall.c: rework nftw hooks to use a global for argument passing
  instead of using nested functions and the resulting trampolines that
  cause an executable stack.  LP: #434813.
* debian/rules: revert powerpc exception, since the cause is fixed by
  removing the nested functions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
189
189
 
190
190
void   delayed_exit         (int code);
191
191
 
 
192
struct {
 
193
        /* com mon */
 
194
        Mount *mnt;
 
195
        /* tmp_hook */
 
196
        int    purge;
 
197
        time_t barrier;
 
198
} nftw_hook_args;
192
199
 
193
200
static const struct {
194
201
        const char *mountpoint;
314
321
static int tmptime = 0;
315
322
 
316
323
 
 
324
static void
 
325
dequote (char *str)
 
326
{
 
327
        size_t len;
 
328
 
 
329
        nih_assert (str != NULL);
 
330
 
 
331
        if ((str[0] != '"') && (str[0] != '\''))
 
332
                return;
 
333
 
 
334
        len = strlen (str);
 
335
        len -= 2;
 
336
 
 
337
        memmove (str, str + 1, len);
 
338
        str[len] = '\0';
 
339
}
 
340
 
317
341
Mount *
318
342
new_mount (const char *mountpoint,
319
343
           const char *device,
341
365
        mnt->fsck_pid = -1;
342
366
        mnt->device_ready = FALSE;
343
367
 
 
368
        if (mnt->device) {
 
369
                if (! strncmp (mnt->device, "UUID=", 5)) {
 
370
                        dequote (mnt->device + 5);
 
371
                } else if (! strncmp (mnt->device, "LABEL=", 6)) {
 
372
                        dequote (mnt->device + 6);
 
373
                } else {
 
374
                        dequote (mnt->device);
 
375
                }
 
376
        }
 
377
 
344
378
        mnt->type = type ? NIH_MUST (nih_strdup (mounts, type)) : NULL;
345
379
        mnt->virtual = FALSE;
346
380
        mnt->opts = opts ? NIH_MUST (nih_strdup (mounts, opts)) : NULL;
385
419
                if (mnt->device)
386
420
                        nih_unref (mnt->device, mounts);
387
421
                mnt->device = NIH_MUST (nih_strdup (mounts, device));
 
422
 
 
423
                if (! strncmp (mnt->device, "UUID=", 5)) {
 
424
                        dequote (mnt->device + 5);
 
425
                } else if (! strncmp (mnt->device, "LABEL=", 6)) {
 
426
                        dequote (mnt->device + 6);
 
427
                } else {
 
428
                        dequote (mnt->device);
 
429
                }
388
430
        }
389
431
 
390
432
        if (check >= 0)
555
597
{
556
598
        nih_assert (mnt != NULL);
557
599
 
558
 
        if (strcmp (mnt->mountpoint, "/")) {
559
 
                return mnt->virtual;
560
 
        } else {
561
 
                return FALSE;
562
 
        }
 
600
        return mnt->virtual;
563
601
}
564
602
 
565
603
int
567
605
{
568
606
        nih_assert (mnt != NULL);
569
607
 
570
 
        if (! strcmp (mnt->mountpoint, "/")) {
571
 
                return FALSE;
572
 
        } else if (has_option (mnt, "_netdev", FALSE)) {
 
608
        if (has_option (mnt, "_netdev", FALSE)) {
573
609
                return TRUE;
574
610
        } else if (! mnt->type) {
575
611
                return FALSE;
632
668
 
633
669
                if (mounts[i].device
634
670
                    && strncmp (mounts[i].device, "/dev/", 5)
635
 
                    && (! mounts[i].virtual)) {
 
671
                    && (! is_virtual (&mounts[i]))) {
636
672
                        paths = NIH_MUST (nih_realloc (paths, NULL,
637
673
                                                       sizeof (Path) * (num_paths + 1)));
638
674
                        path = &paths[num_paths++];
687
723
        }
688
724
 
689
725
        while ((mntent = getmntent (fstab)) != NULL) {
690
 
                Mount *mnt;
 
726
                Mount *         mnt;
 
727
                nih_local char *fsname = NULL;
691
728
 
692
729
                mnt = find_mount (mntent->mnt_dir);
693
730
                if (mnt) {
957
994
                                 sizeof (Mount) * (num_mounts - i - 1));
958
995
                        num_mounts--;
959
996
                        i--;
 
997
                } else if (! strcmp (mounts[i].mountpoint, "/")) {
 
998
                        nih_debug ("local   %s", mounts[i].mountpoint);
960
999
                } else if (is_fhs (&mounts[i])) {
961
1000
                        if (is_virtual (&mounts[i])) {
962
1001
                                nih_debug ("virtual %s", mounts[i].mountpoint);
1006
1045
         */
1007
1046
        mnt->mountpoint_ready = TRUE;
1008
1047
        if (is_virtual (mnt)
 
1048
            || (is_remote (mnt) && mnt->mounted && (! needs_remount (mnt)))
1009
1049
            || (! mnt->type)
1010
1050
            || (mnt->device_ready && (! is_swap (mnt))))
1011
1051
                run_mount (mnt, FALSE);
1056
1096
 
1057
1097
        /* Look at the current table state */
1058
1098
        for (size_t i = 0; i < num_mounts; i++) {
1059
 
                if (is_fhs (&mounts[i])) {
 
1099
                if (! strcmp (mounts[i].mountpoint, "/")) {
 
1100
                        num_fhs++;
 
1101
                        num_local++;
 
1102
                        if (mounts[i].mounted && (! needs_remount (&mounts[i]))) {
 
1103
                                num_fhs_mounted++;
 
1104
                                num_local_mounted++;
 
1105
                        }
 
1106
 
 
1107
                } else if (is_fhs (&mounts[i])) {
1060
1108
                        int mounted = FALSE;
1061
1109
 
1062
1110
                        if (is_virtual (&mounts[i])) {
1408
1456
                   && strcmp (mnt->type, "ntfs")
1409
1457
                   && strcmp (mnt->type, "ntfs-3g")) {
1410
1458
                NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-n"));
 
1459
        } else if (has_showthrough (mnt)) {
 
1460
                NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-n"));
1411
1461
        }
1412
1462
        NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-a"));
1413
1463
        NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-t"));
1775
1825
                if ((rmdir (mountpoint) < 0)
1776
1826
                    && (errno != EEXIST))
1777
1827
                        nih_warn ("rmdir %s: %s", mountpoint, strerror (errno));
 
1828
 
 
1829
                if (written_mtab)
 
1830
                        run_mount (root, TRUE);
1778
1831
        }
1779
1832
}
1780
1833
 
1972
2025
}
1973
2026
 
1974
2027
 
 
2028
int dev_hook_walk (const char *       fpath,
 
2029
                   const struct stat *sb,
 
2030
                   int                typeflag,
 
2031
                   struct FTW *       ftwbuf)
 
2032
{
 
2033
        Mount * mnt = nftw_hook_args.mnt;
 
2034
        char dest[PATH_MAX];
 
2035
 
 
2036
        strcpy (dest, mnt->mountpoint);
 
2037
        strcat (dest, fpath + 17);
 
2038
 
 
2039
        if (S_ISDIR (sb->st_mode)) {
 
2040
                if ((mkdir (dest, sb->st_mode & ~S_IFMT) < 0)
 
2041
                    && (errno != EEXIST))
 
2042
                        nih_warn ("%s: %s", dest, strerror (errno));
 
2043
        } else if (S_ISLNK (sb->st_mode)) {
 
2044
                char target[PATH_MAX];
 
2045
                ssize_t len;
 
2046
 
 
2047
                len = readlink (fpath, target, sizeof target);
 
2048
                target[len] = '\0';
 
2049
 
 
2050
                if ((symlink (target, dest) < 0)
 
2051
                    && (errno != EEXIST))
 
2052
                        nih_warn ("%s: %s", dest, strerror (errno));
 
2053
        } else {
 
2054
                if ((mknod (dest, sb->st_mode, sb->st_rdev) < 0)
 
2055
                    && (errno != EEXIST))
 
2056
                        nih_warn ("%s: %s", dest, strerror (errno));
 
2057
        }
 
2058
 
 
2059
        return FTW_CONTINUE;
 
2060
}
 
2061
 
 
2062
 
1975
2063
int
1976
2064
dev_hook (Mount *mnt)
1977
2065
{
1979
2067
 
1980
2068
        nih_debug ("populating %s", mnt->mountpoint);
1981
2069
 
1982
 
        int dev_hook_walk (const char *       fpath,
1983
 
                           const struct stat *sb,
1984
 
                           int                typeflag,
1985
 
                           struct FTW *       ftwbuf)
1986
 
        {
1987
 
                char dest[PATH_MAX];
1988
 
 
1989
 
                strcpy (dest, mnt->mountpoint);
1990
 
                strcat (dest, fpath + 17);
1991
 
 
1992
 
                if (S_ISDIR (sb->st_mode)) {
1993
 
                        if ((mkdir (dest, sb->st_mode & ~S_IFMT) < 0)
1994
 
                            && (errno != EEXIST))
1995
 
                                nih_warn ("%s: %s", dest, strerror (errno));
1996
 
                } else if (S_ISLNK (sb->st_mode)) {
1997
 
                        char target[PATH_MAX];
1998
 
                        ssize_t len;
1999
 
 
2000
 
                        len = readlink (fpath, target, sizeof target);
2001
 
                        target[len] = '\0';
2002
 
 
2003
 
                        if ((symlink (target, dest) < 0)
2004
 
                            && (errno != EEXIST))
2005
 
                                nih_warn ("%s: %s", dest, strerror (errno));
2006
 
                } else {
2007
 
                        if ((mknod (dest, sb->st_mode, sb->st_rdev) < 0)
2008
 
                            && (errno != EEXIST))
2009
 
                                nih_warn ("%s: %s", dest, strerror (errno));
2010
 
                }
2011
 
 
2012
 
                return FTW_CONTINUE;
2013
 
        }
2014
 
 
2015
 
 
 
2070
        nftw_hook_args.mnt = mnt;
2016
2071
        nftw ("/lib/udev/devices", dev_hook_walk, 1024,
2017
2072
              FTW_ACTIONRETVAL | FTW_PHYS | FTW_MOUNT);
 
2073
        nftw_hook_args.mnt = NULL;
2018
2074
 
2019
2075
        return 0;
2020
2076
}
2021
2077
 
 
2078
int tmp_hook_walk (const char *       fpath,
 
2079
                   const struct stat *sb,
 
2080
                   int                typeflag,
 
2081
                   struct FTW *       ftwbuf)
 
2082
{
 
2083
        Mount * mnt = nftw_hook_args.mnt;
 
2084
        const char *name = fpath + ftwbuf->base;
 
2085
 
 
2086
        if (! ftwbuf->level)
 
2087
                return FTW_CONTINUE;
 
2088
 
 
2089
        if (S_ISDIR (sb->st_mode)) {
 
2090
                if (strcmp (name, "lost+found")
 
2091
                    && (nftw_hook_args.purge
 
2092
                        || ((sb->st_mtime < nftw_hook_args.barrier
 
2093
                             && (sb->st_ctime < nftw_hook_args.barrier)))))
 
2094
                {
 
2095
                        if (rmdir (fpath) < 0)
 
2096
                                nih_warn ("%s: %s", fpath, strerror (errno));
 
2097
                }
 
2098
 
 
2099
        } else {
 
2100
                if (strcmp (name, "quota.user")
 
2101
                    && strcmp (name, "aquota.user")
 
2102
                    && strcmp (name, "quote.group")
 
2103
                    && strcmp (name, "aquota.group")
 
2104
                    && strcmp (name, ".journal")
 
2105
                    && fnmatch ("...security*", name, FNM_PATHNAME)
 
2106
                    && (nftw_hook_args.purge
 
2107
                        || ((sb->st_mtime < nftw_hook_args.barrier)
 
2108
                            && (sb->st_ctime < nftw_hook_args.barrier)
 
2109
                            && (sb->st_atime < nftw_hook_args.barrier))
 
2110
                        || ((ftwbuf->level == 1)
 
2111
                            && (! fnmatch (".X*-lock", fpath + ftwbuf->base, FNM_PATHNAME)))))
 
2112
                {
 
2113
                        if (unlink (fpath) < 0)
 
2114
                                nih_warn ("%s: %s", fpath, strerror (errno));
 
2115
                }
 
2116
 
 
2117
        }
 
2118
 
 
2119
        return FTW_CONTINUE;
 
2120
}
 
2121
 
2022
2122
int
2023
2123
tmp_hook (Mount *mnt)
2024
2124
{
2025
2125
        struct stat statbuf;
2026
 
        int         purge = FALSE;
2027
 
        time_t      barrier;
2028
2126
 
2029
2127
        nih_assert (mnt != NULL);
2030
2128
 
2040
2138
        nih_debug ("cleaning up %s", mnt->mountpoint);
2041
2139
 
2042
2140
        if (tmptime > 0) {
2043
 
                barrier = time (NULL) - (tmptime * 3600);
 
2141
                nftw_hook_args.purge = FALSE;
 
2142
                nftw_hook_args.barrier = time (NULL) - (tmptime * 3600);
2044
2143
        } else {
2045
 
                purge = TRUE;
2046
 
                barrier = 0;
2047
 
        }
2048
 
 
2049
 
        int tmp_hook_walk (const char *       fpath,
2050
 
                           const struct stat *sb,
2051
 
                           int                typeflag,
2052
 
                           struct FTW *       ftwbuf)
2053
 
        {
2054
 
                const char *name = fpath + ftwbuf->base;
2055
 
 
2056
 
                if (! ftwbuf->level)
2057
 
                        return FTW_CONTINUE;
2058
 
 
2059
 
                if (S_ISDIR (sb->st_mode)) {
2060
 
                        if (strcmp (name, "lost+found")
2061
 
                            && (purge
2062
 
                                || ((sb->st_mtime < barrier
2063
 
                                     && (sb->st_ctime < barrier)))))
2064
 
                        {
2065
 
                                if (rmdir (fpath) < 0)
2066
 
                                        nih_warn ("%s: %s", fpath, strerror (errno));
2067
 
                        }
2068
 
 
2069
 
                } else {
2070
 
                        if (strcmp (name, "quota.user")
2071
 
                            && strcmp (name, "aquota.user")
2072
 
                            && strcmp (name, "quote.group")
2073
 
                            && strcmp (name, "aquota.group")
2074
 
                            && strcmp (name, ".journal")
2075
 
                            && fnmatch ("...security*", name, FNM_PATHNAME)
2076
 
                            && (purge
2077
 
                                || ((sb->st_mtime < barrier)
2078
 
                                    && (sb->st_ctime < barrier)
2079
 
                                    && (sb->st_atime < barrier))
2080
 
                                || ((ftwbuf->level == 1)
2081
 
                                    && (! fnmatch (".X*-lock", fpath + ftwbuf->base, FNM_PATHNAME)))))
2082
 
                        {
2083
 
                                if (unlink (fpath) < 0)
2084
 
                                        nih_warn ("%s: %s", fpath, strerror (errno));
2085
 
                        }
2086
 
 
2087
 
                }
2088
 
 
2089
 
                return FTW_CONTINUE;
2090
 
        }
2091
 
 
 
2144
                nftw_hook_args.purge = TRUE;
 
2145
                nftw_hook_args.barrier = 0;
 
2146
        }
 
2147
 
 
2148
        nftw_hook_args.mnt = mnt;
2092
2149
        nftw (mnt->mountpoint, tmp_hook_walk, 1024,
2093
2150
              FTW_ACTIONRETVAL | FTW_DEPTH | FTW_PHYS | FTW_MOUNT);
 
2151
        nftw_hook_args.mnt = NULL;
2094
2152
 
2095
2153
        return 0;
2096
2154
}
2097
2155
 
 
2156
        int var_run_hook_walk (const char *       fpath,
 
2157
                               const struct stat *sb,
 
2158
                               int                typeflag,
 
2159
                               struct FTW *       ftwbuf)
 
2160
        {
 
2161
                Mount * mnt = nftw_hook_args.mnt;
 
2162
                char dest[PATH_MAX];
 
2163
 
 
2164
                strcpy (dest, mnt->mountpoint);
 
2165
                strcat (dest, fpath + 22);
 
2166
 
 
2167
                if (S_ISDIR (sb->st_mode)) {
 
2168
                        if ((mkdir (dest, sb->st_mode & ~S_IFMT) < 0)
 
2169
                            && (errno != EEXIST))
 
2170
                                nih_warn ("%s: %s", dest, strerror (errno));
 
2171
                } else if (S_ISLNK (sb->st_mode)) {
 
2172
                        char target[PATH_MAX];
 
2173
                        ssize_t len;
 
2174
 
 
2175
                        len = readlink (fpath, target, sizeof target);
 
2176
                        target[len] = '\0';
 
2177
 
 
2178
                        if ((symlink (target, dest) < 0)
 
2179
                            && (errno != EEXIST))
 
2180
                                nih_warn ("%s: %s", dest, strerror (errno));
 
2181
                } else {
 
2182
                        int     in_fd;
 
2183
                        int     out_fd;
 
2184
                        char    buf[4096];
 
2185
                        ssize_t len;
 
2186
 
 
2187
                        in_fd = open (fpath, O_RDONLY);
 
2188
                        if (in_fd < 0) {
 
2189
                                nih_warn ("%s: %s", fpath, strerror (errno));
 
2190
                                return FTW_CONTINUE;
 
2191
                        }
 
2192
 
 
2193
                        out_fd = open (dest, O_WRONLY | O_CREAT | O_TRUNC,
 
2194
                                       0644);
 
2195
                        if (out_fd < 0) {
 
2196
                                nih_warn ("%s: %s", dest, strerror (errno));
 
2197
                                close (in_fd);
 
2198
                                return FTW_CONTINUE;
 
2199
                        }
 
2200
 
 
2201
                        while ((len = read (in_fd, buf, sizeof buf)) > 0)
 
2202
                                write (out_fd, buf, len);
 
2203
 
 
2204
                        close (in_fd);
 
2205
                        if (close (out_fd) < 0)
 
2206
                                nih_warn ("%s: %s", dest, strerror (errno));
 
2207
                }
 
2208
 
 
2209
                return FTW_CONTINUE;
 
2210
        }
 
2211
 
 
2212
 
2098
2213
int
2099
2214
var_run_hook (Mount *mnt)
2100
2215
{
2163
2278
 
2164
2279
        nih_debug ("populating %s from initramfs", mnt->mountpoint);
2165
2280
 
2166
 
        int var_run_hook_walk (const char *       fpath,
2167
 
                               const struct stat *sb,
2168
 
                               int                typeflag,
2169
 
                               struct FTW *       ftwbuf)
2170
 
        {
2171
 
                char dest[PATH_MAX];
2172
 
 
2173
 
                strcpy (dest, mnt->mountpoint);
2174
 
                strcat (dest, fpath + 22);
2175
 
 
2176
 
                if (S_ISDIR (sb->st_mode)) {
2177
 
                        if ((mkdir (dest, sb->st_mode & ~S_IFMT) < 0)
2178
 
                            && (errno != EEXIST))
2179
 
                                nih_warn ("%s: %s", dest, strerror (errno));
2180
 
                } else if (S_ISLNK (sb->st_mode)) {
2181
 
                        char target[PATH_MAX];
2182
 
                        ssize_t len;
2183
 
 
2184
 
                        len = readlink (fpath, target, sizeof target);
2185
 
                        target[len] = '\0';
2186
 
 
2187
 
                        if ((symlink (target, dest) < 0)
2188
 
                            && (errno != EEXIST))
2189
 
                                nih_warn ("%s: %s", dest, strerror (errno));
2190
 
                } else {
2191
 
                        int     in_fd;
2192
 
                        int     out_fd;
2193
 
                        char    buf[4096];
2194
 
                        ssize_t len;
2195
 
 
2196
 
                        in_fd = open (fpath, O_RDONLY);
2197
 
                        if (in_fd < 0) {
2198
 
                                nih_warn ("%s: %s", fpath, strerror (errno));
2199
 
                                return FTW_CONTINUE;
2200
 
                        }
2201
 
 
2202
 
                        out_fd = open (dest, O_WRONLY | O_CREAT | O_TRUNC,
2203
 
                                       0644);
2204
 
                        if (out_fd < 0) {
2205
 
                                nih_warn ("%s: %s", dest, strerror (errno));
2206
 
                                close (in_fd);
2207
 
                                return FTW_CONTINUE;
2208
 
                        }
2209
 
 
2210
 
                        while ((len = read (in_fd, buf, sizeof buf)) > 0)
2211
 
                                write (out_fd, buf, len);
2212
 
 
2213
 
                        close (in_fd);
2214
 
                        if (close (out_fd) < 0)
2215
 
                                nih_warn ("%s: %s", dest, strerror (errno));
2216
 
                }
2217
 
 
2218
 
                return FTW_CONTINUE;
2219
 
        }
2220
 
 
2221
 
 
 
2281
        nftw_hook_args.mnt = mnt;
2222
2282
        nftw ("/dev/.initramfs/varrun", var_run_hook_walk, 1024,
2223
2283
              FTW_ACTIONRETVAL | FTW_PHYS | FTW_MOUNT);
 
2284
        nftw_hook_args.mnt = NULL;
2224
2285
 
2225
2286
        return 0;
2226
2287
}