X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Fsecure-mount.c;h=08d83d4650f63399c7a4ff837e87f59ae75f1d5d;hb=5f3e8dc9d268523560cae12fdb8e93663a3ead72;hp=8b72ace9e8eec3f43a9aafb39ff56a3449807b04;hpb=36bfe6c2668bbce4ec6091821d749c78e54feca9;p=util-vserver.git diff --git a/util-vserver/src/secure-mount.c b/util-vserver/src/secure-mount.c index 8b72ace..08d83d4 100644 --- a/util-vserver/src/secure-mount.c +++ b/util-vserver/src/secure-mount.c @@ -16,13 +16,12 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - // secure-mount [--secure] [--chroot ] + // secure-mount [--chroot] // [--mtab ] [--fstab ] // - // 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 @@ -32,12 +31,15 @@ #include "util.h" #include "pathconfig.h" +#include + #include #include #include #include #include #include +#include #include #include #include @@ -48,26 +50,35 @@ #include #include #include +#include +#include + +#define ENSC_WRAPPERS_FCNTL 1 +#include #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; + unsigned long mask; 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; }; @@ -77,6 +88,10 @@ struct Options { #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[] = { @@ -86,50 +101,100 @@ 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 ] [-n]\n" - " [--mtab ] [--fstab ] [--chroot ] \n" - " [--secure] -a|([-o ] [--] )\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 ] [--chroot]\n" + " [--mtab ] [--fstab ] [--rootfs yes|no|only]\n" + " [-n] -a|([-o ] [--] )\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 ... assume the given filesystem type\n" + " -o ... set additional options; see mount(2) for details\n" + " -n ... do not update the mtab-file\n" + " --mtab ... use as an alternative mtab file\n" + " [default: /etc/mtab]\n" + " --chroot ... chroot into the current directory before\n" + " mounting the filesystem\n" + " --fstab ... use 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" + " ... the source-filesystem; this path is absolute\n" + " to the current root-filesystem. Only valid\n" + " without the '-a' option.\n" + " ... 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); @@ -155,73 +220,6 @@ isSameObject(struct stat const *lhs, } static int -chdirSecure(char const *dir) -{ - 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); - } - - return 0; -} - -static int -verifyPosition(char const *mntpoint, char const *dir1, char const *dir2) -{ - 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; - } - - return 0; -} - -static int fchroot(int fd) { if (fchdir(fd)==-1 || chroot(".")==-1) return -1; @@ -241,6 +239,24 @@ writeStrX(int fd, char const *str) return writeX(fd, str, strlen(str)); } +static inline char const * +getType(struct MountInfo const *mnt) +{ + if (mnt->type==0) return "none"; + else if (strncmp(mnt->type, "ext", 3)==0) return "ufs"; + else return mnt->type; +} + +inline static void +restoreRoot(struct Options const *opt) +{ + 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 updateMtab(struct MountInfo const *mnt, struct Options const *opt) { @@ -248,45 +264,41 @@ updateMtab(struct MountInfo const *mnt, struct Options const *opt) 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()"); + 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 @@ -302,14 +314,23 @@ callExternalMount(struct MountInfo const *mnt) 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 && + argv[idx++] = "-o"; + if (mnt->data && *mnt->data && strcmp(mnt->data, "defaults")!=0) { - argv[idx++] = "-o"; - argv[idx++] = mnt->data; + if (mnt->mask & MS_NODEV) + argv[idx++] = mnt->data; + else { + char * tmp = alloca(strlen(mnt->data) + sizeof("nodev,")); + strcpy(tmp, "nodev,"); + strcat(tmp, mnt->data); + argv[idx++] = tmp; + } } + else + argv[idx++] = "nodev"; if (mnt->type) { argv[idx++] = "-t"; @@ -322,74 +343,81 @@ callExternalMount(struct MountInfo const *mnt) 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)) { + unsigned long flag = mnt->flag; + if ((flag & MS_NODEV)==0) flag |= MS_NODEV; + if (mount(mnt->src, ".", mnt->type ? mnt->type : "", - mnt->flags, mnt->data)==-1) { - perror("mount()"); + 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) { @@ -400,50 +428,58 @@ mountSingle(struct MountInfo const *mnt, struct Options const *opt) 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; iopt, 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->mask |= opt->mask; + 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) + 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=='#' || *buf=='\0') return prIGNORE; @@ -453,22 +489,41 @@ parseFstabLine(struct MountInfo *info, char *buf) 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->flag = MS_NODEV; + info->mask = 0; + info->xflag = 0; - info->flags = 0; - info->noauto = false; - if (!transformOptionList(info)) return prFAIL; - if (info->noauto) return prIGNORE; + if (strcmp(info->type, "swap") ==0) return prIGNORE; + else if (strcmp(info->type, "none") ==0) info->type = 0; + else if (strcmp(info->type, "devpts")==0) info->mask |= MS_NODEV; + + 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) { @@ -479,55 +534,56 @@ mountFstab(struct Options const *opt) assert(opt->fstab!=0); fd = open(opt->fstab, O_RDONLY); if (fd==-1) { - perror("open()"); + perror("secure-mount: open()"); 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()"); + perror("secure-mount: lseek()"); goto err1; } { 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] = '#'; // 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)) { + switch (parseFstabLine(&mnt, ptr, &col_nr)) { case prFAIL : - WRITE_MSG(2, "Failed to parse 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; } } @@ -537,34 +593,52 @@ mountFstab(struct Options const *opt) 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, + .do_chroot = 0, .ignore_mtab = false, .mount_all = false, - .is_secure = false, - .cur_rootdir_fd = -1 + .cur_dir_fd = -1, + .cur_rootdir_fd = -1, + .rootfs = rfsYES }; - opt.cur_rootdir_fd = open("/", O_RDONLY|O_DIRECTORY); - - 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; @@ -576,12 +650,16 @@ int main(int argc, char *argv[]) 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]); @@ -591,11 +669,15 @@ int main(int argc, char *argv[]) } } + if (opt.mount_all && optind 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; @@ -608,7 +690,7 @@ int main(int argc, char *argv[]) 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; }