// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- // secure-mount <general mount(8) options> [--secure] [--chroot <dir>]
+ // secure-mount <general mount(8) options> [--chroot]
// [--mtab <mtabfile>] [--fstab <fstabfile>]
//
- // Executes mount-operations in the given chroot-dir: it assumes sources in
- // the current root-dir while destinations are expected in the chroot
- // environment. When '--secure' is given, the destination must not contain
- // symlinks.
+ // Executes mount-operations under the current directory: it assumes sources
+ // in the current root-dir while destinations are expected in the chroot
+ // environment.
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include "compat.h"
#include "util.h"
#include "pathconfig.h"
+#include <lib/internal.h>
+
#include <getopt.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/mount.h>
#include <assert.h>
#include <ctype.h>
#include <sys/wait.h>
+#include <libgen.h>
+#include <signal.h>
+
+#define ENSC_WRAPPERS_FCNTL 1
+#include <wrappers.h>
#define MNTPOINT "/etc"
+typedef enum { rfsYES, rfsNO, rfsONLY } RootFsOption;
+
struct MountInfo {
char const * src;
char const * dst;
char const * type;
- unsigned long flags;
+ unsigned long flag;
+ unsigned long xflag;
char * data;
- bool noauto;
};
struct Options {
char const * mtab;
char const * fstab;
- char const * rootdir;
+ bool do_chroot;
bool ignore_mtab;
bool mount_all;
- bool is_secure;
+ RootFsOption rootfs;
+ int cur_dir_fd;
int cur_rootdir_fd;
};
#define OPTION_FSTAB 1027
#define OPTION_CHROOT 1028
#define OPTION_SECURE 1029
+#define OPTION_RBIND 1030
+#define OPTION_ROOTFS 1031
+
+#define XFLAG_NOAUTO 0x01
static struct option const
CMDLINE_OPTIONS[] = {
{ "move", no_argument, 0, OPTION_MOVE },
{ "mtab", required_argument, 0, OPTION_MTAB },
{ "fstab", required_argument, 0, OPTION_FSTAB },
- { "chroot", required_argument, 0, OPTION_CHROOT },
+ { "rootfs", required_argument, 0, OPTION_ROOTFS },
+ { "chroot", no_argument, 0, OPTION_CHROOT },
{ "secure", no_argument, 0, OPTION_SECURE },
+ { "rbind", no_argument, 0, OPTION_RBIND },
{ 0, 0, 0, 0 }
};
-static struct FstabOptions {
+#ifndef MS_REC
+# define MS_REC 0x4000
+#endif
+
+static struct FstabOption {
char const * const opt;
- unsigned long const or_flag;
- unsigned long const and_flag;
- bool const is_dflt;
+ unsigned long const flag;
+ unsigned long const mask;
+ unsigned long const xflag;
+ bool const is_dflt;
} const FSTAB_OPTIONS[] = {
- { "bind", MS_BIND, ~0, false },
- { "move", MS_MOVE, ~0, false },
-#if 0
- { "noatime", MS_NOATIME, ~0, false },
- { "mandlock", MS_MANDLOCK, ~0, false },
- { "nodev", MS_NODEV, ~0, false },
- { "nodiratime", MS_NODIRATIME, ~0, false },
- { "noexec", MS_NOEXEC, ~0, false },
- { "nosuid", MS_NOSUID, ~0, false },
- { "rdonly", MS_RDONLY, ~0, false },
- { "remount", MS_REMOUNT, ~0, false },
- { "sync", MS_SYNCHRONOUS, ~0, false },
+ { "defaults", 0, (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|
+ MS_SYNCHRONOUS), 0, false },
+ { "rbind", MS_BIND|MS_REC, MS_BIND|MS_REC, 0, false },
+ { "bind", MS_BIND, MS_BIND, 0, false },
+ { "move", MS_MOVE, MS_MOVE, 0, false },
+ { "async", 0, MS_SYNCHRONOUS, 0, false },
+ { "sync", MS_SYNCHRONOUS, MS_SYNCHRONOUS, 0, false },
+ { "atime", 0, MS_NOATIME, 0, false },
+ { "noatime", MS_NOATIME, MS_NOATIME, 0, false },
+ { "dev", 0, MS_NODEV, 0, false },
+ { "nodev", MS_NODEV, MS_NODEV, 0, false },
+ { "exec", 0, MS_NOEXEC, 0, false },
+ { "noexec", MS_NOEXEC, MS_NOEXEC, 0, false },
+ { "suid", 0, MS_NOSUID, 0, false },
+ { "nosuid", MS_NOSUID, MS_NOSUID, 0, false },
+ { "ro", MS_RDONLY, MS_RDONLY, 0, false },
+ { "rw", 0, MS_RDONLY, 0, false },
+
+ { "remount", MS_REMOUNT, MS_REMOUNT, 0, false },
+ { "users", MS_NOEXEC|MS_NOSUID|MS_NODEV,
+ MS_NOEXEC|MS_NOSUID|MS_NODEV, 0, false },
+ { "mandlock", MS_MANDLOCK, MS_MANDLOCK, 0, false },
+ { "nodiratime", MS_NODIRATIME, MS_NODIRATIME, 0, false },
#ifdef MS_DIRSYNC
- { "dirsync", MS_DIRSYNC, ~0, false },
-#endif
+ { "dirsync", MS_DIRSYNC, MS_DIRSYNC, 0, false },
#endif
- { "", 0, 0, false }
+ { "_netdev", 0, 0, 0, false },
+ { "auto", 0, 0, 0, false },
+ { "noauto", 0, 0, XFLAG_NOAUTO, false },
+ { "user", 0, 0, 0, false },
+ { "nouser", 0, 0, 0, false },
};
+int wrapper_exit_code = 1;
+
static void
showHelp(int fd, char const *cmd, int res)
{
+ VSERVER_DECLARE_CMD(cmd);
+
WRITE_MSG(fd, "Usage: ");
WRITE_STR(fd, cmd);
WRITE_MSG(fd,
- " [--help] [--version] [--bind] [--move] [-t <type>] [-n]\n"
- " [--mtab <filename>] [--fstab <filename>] [--chroot <dirname>] \n"
- " [--secure] -a|([-o <options>] [--] <src> <dst>)\n\n"
- "Executes mount-operations in the given chroot-dir: it assumes sources in the\n"
- "current root-dir while destinations are expected in the chroot environment.\n"
- "When '--secure' is given, the destination must not contain symlinks.\n\n"
+ " [--help] [--version] [--bind] [--move] [--rbind] [-t <type>] [--chroot]\n"
+ " [--mtab <filename>] [--fstab <filename>] [--rootfs yes|no|only]\n"
+ " [-n] -a|([-o <options>] [--] <src> <dst>)\n\n"
+ "Executes mount-operations under the current directory: it assumes sources in\n"
+ "the current root-dir while destinations are expected in the chroot environment.\n\n"
"For non-trivial mount-operations it uses the external 'mount' program which\n"
"can be overridden by the $MOUNT environment variable.\n\n"
+ "Options:\n"
+ " --bind|move|rbind ... set the correspond flags; with this options\n"
+ " the mount will be executed internally without\n"
+ " calling an external mount program.\n"
+ " -t <type> ... assume the given filesystem type\n"
+ " -o <options> ... set additional options; see mount(2) for details\n"
+ " -n ... do not update the mtab-file\n"
+ " --mtab <filename> ... use <filename> as an alternative mtab file\n"
+ " [default: /etc/mtab]\n"
+ " --chroot ... chroot into the current directory before\n"
+ " mounting the filesystem\n"
+ " --fstab <filename> ... use <filename> as an alternative fstab file;\n"
+ " this option has an effect only with the '-a'\n"
+ " option [default: /etc/fstab]\n"
+ " --rootfs yes|no|only ... specifies how to handle an entry for a rootfs\n"
+ " ('/') when processing an fstab file. 'yes' will\n"
+ " mount it among the other entries, 'only' will\n"
+ " mount only the rootfs entry, and 'no' will ignore\n"
+ " it and mount only the other entries [default: yes]\n"
+ " -a ... mount everything listed in the fstab-file\n\n"
+ " <src> ... the source-filesystem; this path is absolute\n"
+ " to the current root-filesystem. Only valid\n"
+ " without the '-a' option.\n"
+ " <dst> ... the destination mount-point; when used with\n"
+ " '--chroot', this path is relative to the current\n"
+ " directory. Only valid without the '-a' option\n\n"
"Please report bugs to " PACKAGE_BUGREPORT "\n");
exit(res);
}
static int
-chdirSecure(char const *dir)
+fchroot(int fd)
{
- char tmp[strlen(dir)+1], *ptr;
- char const *cur;
-
- strcpy(tmp, dir);
- cur = strtok_r(tmp, "/", &ptr);
- while (cur) {
- struct stat pre_stat, post_stat;
-
- if (lstat(cur, &pre_stat)==-1) return -1;
-
- if (!S_ISDIR(pre_stat.st_mode)) {
- errno = ENOENT;
- return -1;
- }
- if (S_ISLNK(pre_stat.st_mode)) {
- errno = EINVAL;
- return -1;
- }
-
- if (chdir(cur)==-1) return -1;
- if (stat(".", &post_stat)==-1) return -1;
-
- if (!isSameObject(&pre_stat, &post_stat)) {
- char dir[PATH_MAX];
-
- WRITE_MSG(2, "Possible symlink race ATTACK at '");
- WRITE_STR(2, getcwd(dir, sizeof(dir)));
- WRITE_MSG(2, "'\n");
-
- errno = EINVAL;
- return -1;
- }
-
- cur = strtok_r(0, "/", &ptr);
- }
-
+ if (fchdir(fd)==-1 || chroot(".")==-1) return -1;
return 0;
}
static int
-verifyPosition(char const *mntpoint, char const *dir1, char const *dir2)
+writeX(int fd, void const *buf, size_t len)
{
- struct stat pre_stat, post_stat;
-
- if (stat(mntpoint, &pre_stat)==-1) return -1;
- if (chroot(dir1)==-1 || chdir(dir2)==-1) return -1;
- if (stat(".", &post_stat)==-1) return -1;
-
- if (!isSameObject(&pre_stat, &post_stat)) {
- char dir[PATH_MAX];
-
- WRITE_MSG(2, "Possible symlink race ATTACK at '");
- WRITE_STR(2, getcwd(dir, sizeof(dir)));
- WRITE_MSG(2, "' within '");
- WRITE_STR(2, dir1);
- WRITE_STR(2, "'\n");
-
- errno = EINVAL;
- return -1;
- }
-
+ if ((size_t)(write(fd, buf, len))!=len) return -1;
return 0;
}
static int
-fchroot(int fd)
+writeStrX(int fd, char const *str)
{
- if (fchdir(fd)==-1 || chroot(".")==-1) return -1;
- return 0;
+ return writeX(fd, str, strlen(str));
}
-static int
-writeX(int fd, void const *buf, size_t len)
+static inline char const *
+getType(struct MountInfo const *mnt)
{
- if (write(fd, buf, len)!=len) return -1;
- return 0;
+ if (mnt->type==0) return "none";
+ else if (strncmp(mnt->type, "ext", 3)==0) return "ufs";
+ else return mnt->type;
}
-static int
-writeStrX(int fd, char const *str)
+inline static void
+restoreRoot(struct Options const *opt)
{
- return writeX(fd, str, strlen(str));
+ if (opt->do_chroot!=0 && fchroot(opt->cur_rootdir_fd)==-1) {
+ perror("secure-mount: fchdir(\"/\")");
+ WRITE_MSG(2, "Failed to restore root-directory; aborting\n");
+ exit(1);
+ }
}
static int
int fd;
assert(opt->mtab!=0);
- if (opt->rootdir!=0 &&
- chroot(opt->rootdir)==-1) {
- perror("chroot()");
+ if (opt->do_chroot && fchroot(opt->cur_dir_fd)==-1) {
+ perror("secure-mount: fchroot(\".\")");
return -1;
}
fd=open(opt->mtab, O_CREAT|O_APPEND|O_WRONLY, 0644);
- if (fd==-1) perror("open()");
-
- if (fchroot(opt->cur_rootdir_fd)==-1) {
- perror("fchroot()");
- goto err1;
+ if (fd==-1) {
+ perror("secure-mount: open(<mtab>)");
+ goto err0;
}
- if (fd==-1) goto err0;
-
if (flock(fd, LOCK_EX)==-1) {
- perror("flock()");
+ perror("secure-mount: flock()");
goto err1;
}
-
if (writeStrX(fd, mnt->src)==-1 ||
writeStrX(fd, " ")==-1 ||
writeStrX(fd, mnt->dst)==-1 ||
writeStrX(fd, " ")==-1 ||
- writeStrX(fd, mnt->type ? mnt->type : "none")==-1 ||
+ writeStrX(fd, getType(mnt))==-1 ||
writeStrX(fd, " ")==-1 ||
writeStrX(fd, mnt->data ? mnt->data : "defaults")==-1 ||
writeStrX(fd, " 0 0\n")==-1) {
- perror("write()");
+ perror("secure-mount: write()");
goto err1;
}
res = 0;
err1: close(fd);
- err0: return res;
+ err0:
+ restoreRoot(opt);
+ return res;
}
static bool
argv[idx++] = mount_prog;
argv[idx++] = "-n";
- if (mnt->flags & MS_BIND) argv[idx++] = "--bind";
- else if (mnt->flags & MS_MOVE) argv[idx++] = "--move";
+ if (mnt->flag & MS_BIND) argv[idx++] = "--bind";
+ else if (mnt->flag & MS_MOVE) argv[idx++] = "--move";
- if (mnt->data) {
+ if (mnt->data &&
+ strcmp(mnt->data, "defaults")!=0) {
argv[idx++] = "-o";
argv[idx++] = mnt->data;
}
pid = fork();
if (pid==-1) {
- perror("fork()");
+ perror("secure-mount: fork()");
return false;
}
if (pid==0) {
execv(mount_prog, const_cast(char **)(argv));
- perror("execv()");
+ PERROR_Q("secure-mount: execv", mount_prog);
exit(1);
}
if (wait4(pid, &status, 0, 0)==-1) {
- perror("wait4()");
+ perror("secure-mount: wait4()");
return false;
}
return (WIFEXITED(status)) && (WEXITSTATUS(status)==0);
}
-static bool
-mountSingle(struct MountInfo const *mnt, struct Options const *opt)
+inline static bool
+secureChdir(char const *dir, struct Options const *opt)
{
- char const *dir = mnt->dst;
-
- assert(mnt->dst!=0);
+ int dir_fd;
+ bool res = false;
- if (opt->rootdir!=0) {
- if (chdir(opt->rootdir)==-1) {
- perror("chdir()");
- return false;
- }
-
- while (*dir=='/') ++dir;
+ if (opt->do_chroot!=0 && fchroot(opt->cur_dir_fd)==-1) {
+ perror("secure-mount: fchroot(\".\")");
+ return false;
}
- if (opt->is_secure) {
- if (chdirSecure(dir)==-1) {
- perror("chdirSecure()");
- return false;
- }
+ if (chdir(dir)==-1) {
+ PERROR_Q("secure-mount: chdir", dir);
+ goto err;
}
- else {
- if (*dir!='\0' &&
- chdir(dir)==-1) {
- perror("chdir()");
- return false;
- }
+
+ dir_fd = open(".", O_RDONLY|O_DIRECTORY);
+ if (dir_fd==-1) {
+ perror("secure-mount: open(\".\")");
+ goto err;
}
- if (mnt->flags&MS_BIND) {
+ restoreRoot(opt);
+ if (fchdir(dir_fd)==-1)
+ PERROR_Q("secure-mount: fchdir", dir);
+ else
+ res = true;
+
+ close(dir_fd);
+ return res;
+
+ err:
+ restoreRoot(opt);
+ return false;
+}
+
+static bool
+mountSingle(struct MountInfo const *mnt, struct Options const *opt)
+{
+ assert(mnt->dst!=0);
+
+ if (!secureChdir(mnt->dst, opt))
+ return false;
+
+ if (mnt->flag & (MS_BIND|MS_MOVE)) {
if (mount(mnt->src, ".",
mnt->type ? mnt->type : "",
- mnt->flags, mnt->data)==-1) {
- perror("mount()");
+ mnt->flag, mnt->data)==-1) {
+ perror("secure-mount: mount()");
return false;
}
}
- else {
- if (!callExternalMount(mnt)) return false;
- }
-
- // Check if directories were moved between the chdirSecure() and mount(2)
- if ((mnt->flags&MS_BIND) && opt->rootdir!=0 &&
- (verifyPosition(mnt->src, opt->rootdir, mnt->dst)==-1 ||
- fchroot(opt->cur_rootdir_fd)==-1)) {
- perror("verifyPosition/fchroot");
- // TODO: what is with unmounting?
+ else if (!callExternalMount(mnt))
return false;
- }
if (!opt->ignore_mtab &&
updateMtab(mnt, opt)==-1) {
return true;
}
-static bool
-searchAndRemoveOption(char *buf, char const *needle)
+static struct FstabOption const *
+searchOption(char const *opt, size_t len)
{
- char *pos = strstr(buf, needle);
- size_t len = strlen(needle);
-
- if (pos==0) return false;
- if (pos>buf && pos[-1]!=',') return false;
- if (pos[len]!=',' && pos[len]!='\0') return false;
+ struct FstabOption const * i;
+ for (i=FSTAB_OPTIONS+0; i<FSTAB_OPTIONS+DIM_OF(FSTAB_OPTIONS); ++i)
+ if (strncmp(i->opt, opt, len)==0) return i;
- if (pos>buf || pos[len]!='\0') ++len;
- if (pos>buf) --pos;
-
- memmove(pos, pos+len, strlen(pos+len));
- return true;
+ return 0;
}
static bool
-transformOptionList(struct MountInfo *info)
+transformOptionList(struct MountInfo *info, size_t UNUSED *col)
{
- struct FstabOptions const * flag;
+ char const * ptr = info->data;
+
+ do {
+ char const * pos = strchr(ptr, ',');
+ struct FstabOption const * opt;
- for (flag=FSTAB_OPTIONS; flag->opt[0]!='\0'; ++flag) {
- if (searchAndRemoveOption(info->data, flag->opt) || flag->is_dflt) {
- info->flags &= flag->and_flag;
- info->flags |= flag->or_flag;
+ if (pos==0) pos = ptr+strlen(ptr);
+ opt = searchOption(ptr, pos-ptr);
+
+ if (opt!=0) {
+ info->flag &= ~opt->mask;
+ info->flag |= opt->flag;
+ info->xflag |= opt->xflag;
}
- }
- if (searchAndRemoveOption(info->data, "noauto"))
- info->noauto = true;
+ if (*pos!='\0')
+ ptr = pos+1;
+ else
+ ptr = pos;
+
+ } while (*ptr!='\0');
return true;
}
#define MOVE_TO_NEXT_FIELD(PTR,ALLOW_EOL) \
while (!isspace(*PTR) && *PTR!='\0') ++PTR; \
+ if (col) *col = buf-start_buf+1; \
if (!(ALLOW_EOL) && *PTR=='\0') return prFAIL; \
*PTR++ = '\0'; \
while (isspace(*PTR)) ++PTR
static enum {prDOIT, prFAIL, prIGNORE}
-parseFstabLine(struct MountInfo *info, char *buf, struct Options const *opt)
+ parseFstabLine(struct MountInfo *info, char *buf, size_t *col)
{
+ char const * const start_buf = buf;
+ size_t err_col;
+
while (isspace(*buf)) ++buf;
- if (*buf=='#') return prIGNORE;
+ if (*buf=='#' || *buf=='\0') return prIGNORE;
info->src = buf;
MOVE_TO_NEXT_FIELD(buf, false);
MOVE_TO_NEXT_FIELD(buf, false);
info->type = buf;
MOVE_TO_NEXT_FIELD(buf, false);
+ err_col = buf-start_buf+1;
info->data = buf;
MOVE_TO_NEXT_FIELD(buf, true);
if (strcmp(info->type, "swap")==0) return prIGNORE;
if (strcmp(info->type, "none")==0) info->type = 0;
- info->flags = 0;
- info->noauto = false;
- if (!transformOptionList(info)) return prFAIL;
- if (info->noauto) return prIGNORE;
+ info->flag = 0;
+ info->xflag = 0;
+ if (col) *col = err_col;
+ if (!transformOptionList(info,col)) return prFAIL;
+ if (info->xflag & XFLAG_NOAUTO) return prIGNORE;
return prDOIT;
}
#undef MOVE_TO_NEXT_FIELD
+static void
+showFstabPosition(int fd, char const *fname, size_t line_nr, size_t col_nr)
+{
+ char buf[3*sizeof(line_nr)*2 + 4];
+ size_t len = utilvserver_fmt_uint(buf+1, line_nr)+1;
+
+ buf[0] = ':';
+ buf[len++] = ':';
+ len += utilvserver_fmt_uint(buf+len, col_nr);
+ WRITE_STR(fd, fname);
+ write(fd, buf, len);
+}
+
+
static bool
mountFstab(struct Options const *opt)
{
assert(opt->fstab!=0);
fd = open(opt->fstab, O_RDONLY);
if (fd==-1) {
- perror("open(<fstab>)");
+ perror("secure-mount: open(<fstab>)");
goto err0;
}
- len = lseek(fd, 0, SEEK_END);
+ len = lseek(fd, 0, SEEK_END);
if (len==-1 ||
lseek(fd, 0, SEEK_SET)==-1) {
- perror("lseek(<fstab>)");
+ perror("secure-mount: lseek(<fstab>)");
goto err1;
}
{
- char buf[len+1];
+ char buf[len+2];
char *ptr, *ptrptr;
+ size_t line_nr=0, col_nr;
if (read(fd, buf, len+1)!=len) {
- perror("read()");
+ perror("secure-mount: read()");
goto err1;
}
- buf[len] = '\0';
+ buf[len] = '#'; // workaround for broken dietlibc strtok_r()
+ // implementation
+ buf[len+1] = '\0';
+ ptrptr = buf;
- ptr = strtok_r(buf, "\n", &ptrptr);
- while (ptr) {
+ while ((ptr=strsep(&ptrptr, "\n")) != 0) {
struct MountInfo mnt;
- char * new_ptr = strtok_r(0, "\n", &ptrptr);
+ ++line_nr;
- switch (parseFstabLine(&mnt, ptr, opt)) {
+ switch (parseFstabLine(&mnt, ptr, &col_nr)) {
case prFAIL :
- WRITE_MSG(2, "Failed to parse/mount fstab-line beginning with '");
- WRITE_STR(2, ptr);
- WRITE_MSG(2, "'\n");
+ showFstabPosition(2, opt->fstab, line_nr, col_nr);
+ WRITE_MSG(2, ": syntax error\n");
goto err1;
case prIGNORE : break;
- case prDOIT :
+ case prDOIT : {
+ bool is_rootfs = (strcmp(mnt.dst, "/")==0);
chdir("/");
- if (!mountSingle(&mnt, opt)) {
- WRITE_MSG(2, "Failed to mount fstab-line beginning with '");
- WRITE_STR(2, ptr);
- WRITE_MSG(2, "'\n");
+ if (( is_rootfs && opt->rootfs==rfsNO) ||
+ (!is_rootfs && opt->rootfs==rfsONLY)) { /* ignore the entry */ }
+ else if (!mountSingle(&mnt, opt)) {
+ showFstabPosition(2, opt->fstab, line_nr, 1);
+ WRITE_MSG(2, ": failed to mount fstab-entry\n");
}
break;
+ }
default :
assert(false);
}
-
- ptr = new_ptr;
}
}
err0: return res;
}
+static void
+initFDs(struct Options *opt)
+{
+ opt->cur_dir_fd = Eopen(".", O_RDONLY|O_DIRECTORY, 0);
+ opt->cur_rootdir_fd = Eopen("/", O_RDONLY|O_DIRECTORY, 0);
+
+ Efcntl(opt->cur_dir_fd, F_SETFD, FD_CLOEXEC);
+ Efcntl(opt->cur_rootdir_fd, F_SETFD, FD_CLOEXEC);
+}
+
+static RootFsOption
+parseRootFS(char const *str)
+{
+ if (strcasecmp(str, "yes")==0) return rfsYES;
+ else if (strcasecmp(str, "no")==0) return rfsNO;
+ else if (strcasecmp(str, "only")==0) return rfsONLY;
+ else {
+ WRITE_MSG(2, "secure-mount: invalid option for '--rootfs': '");
+ WRITE_STR(2, str);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+}
+
int main(int argc, char *argv[])
{
struct MountInfo mnt = {
.src = 0,
.dst = 0,
.type = 0,
- .flags = 0,
+ .flag = 0,
+ .xflag = 0,
.data = 0,
- .noauto = false
};
struct Options opt = {
- .mtab = "/etc/mtab",
- .fstab = "/etc/fstab",
- .rootdir = 0,
- .ignore_mtab = false,
- .mount_all = false,
- .is_secure = false,
-
- .cur_rootdir_fd = open("/", O_RDONLY|O_DIRECTORY)
+ .mtab = "/etc/mtab",
+ .fstab = "/etc/fstab",
+ .do_chroot = 0,
+ .ignore_mtab = false,
+ .mount_all = false,
+ .cur_dir_fd = -1,
+ .cur_rootdir_fd = -1,
+ .rootfs = rfsYES
};
- if (opt.cur_rootdir_fd==-1) {
- perror("open(\"/\")");
- return EXIT_FAILURE;
- }
-
while (1) {
int c = getopt_long(argc, argv, "ht:nao:", CMDLINE_OPTIONS, 0);
if (c==-1) break;
switch (c) {
- case 'h' : showHelp(2, argv[0], 0);
+ case 'h' : showHelp(1, argv[0], 0);
case 'v' : showVersion();
case 't' : mnt.type = optarg; break;
case 'n' : opt.ignore_mtab = true; break;
case 'a' : opt.mount_all = true; break;
case 'o' : mnt.data = optarg; break;
- case OPTION_BIND : mnt.flags |= MS_BIND; break;
- case OPTION_MOVE : mnt.flags |= MS_MOVE; break;
+ case OPTION_RBIND : mnt.flag |= MS_REC; /*@fallthrough@*/
+ case OPTION_BIND : mnt.flag |= MS_BIND; break;
+ case OPTION_MOVE : mnt.flag |= MS_MOVE; break;
case OPTION_MTAB : opt.mtab = optarg; break;
case OPTION_FSTAB : opt.fstab = optarg; break;
- case OPTION_CHROOT: opt.rootdir = optarg; break;
- case OPTION_SECURE: opt.is_secure = true; break;
+ case OPTION_CHROOT: opt.do_chroot = true; break;
+ case OPTION_ROOTFS: opt.rootfs = parseRootFS(optarg); break;
+ case OPTION_SECURE:
+ WRITE_MSG(2, "secure-mount: The '--secure' option is deprecated...\n");
+ break;
default :
WRITE_MSG(2, "Try '");
WRITE_STR(2, argv[0]);
}
}
+
if (opt.mount_all && optind<argc) {
WRITE_MSG(2, "Can not specify <src> and '-a' at the same time\n");
return EXIT_FAILURE;
}
+ initFDs(&opt);
+ signal(SIGCHLD, SIG_DFL);
+
if (opt.mount_all) {
if (!mountFstab(&opt)) return EXIT_FAILURE;
else return EXIT_SUCCESS;
if (mnt.data) {
mnt.data = strdup(mnt.data);
- if (!transformOptionList(&mnt)) {
+ if (!transformOptionList(&mnt, 0)) {
WRITE_MSG(2, "Invalid options specified\n");
return EXIT_FAILURE;
}