X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Fsecure-mount.c;h=a7abd19fa4c3c83a80a6fd43830526d1d273b4dd;hb=a917f24ef7b003dcef54a3db2644cf9cb4bc2db2;hp=81fee1fd6bdc1b8042c325bf66edd68d10f71ed6;hpb=f2d2335da3dcc2cb700af4c41c2365d5771cbf7b;p=util-vserver.git diff --git a/util-vserver/src/secure-mount.c b/util-vserver/src/secure-mount.c index 81fee1f..a7abd19 100644 --- a/util-vserver/src/secure-mount.c +++ b/util-vserver/src/secure-mount.c @@ -56,9 +56,9 @@ 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 { @@ -80,6 +80,8 @@ struct Options { #define OPTION_SECURE 1029 #define OPTION_RBIND 1030 +#define XFLAG_NOAUTO 0x01 + static struct option const CMDLINE_OPTIONS[] = { { "help", no_argument, 0, 'h' }, @@ -94,29 +96,48 @@ CMDLINE_OPTIONS[] = { { 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 }, + { "dirsync", MS_DIRSYNC, MS_DIRSYNC, 0, false }, #endif -#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 }, }; static void @@ -255,23 +276,23 @@ updateMtab(struct MountInfo const *mnt, struct Options const *opt) if (opt->rootdir!=0 && chroot(opt->rootdir)==-1) { - perror("chroot()"); + perror("secure-mount: chroot()"); return -1; } fd=open(opt->mtab, O_CREAT|O_APPEND|O_WRONLY, 0644); - if (fd==-1) perror("open()"); + if (fd==-1) perror("secure-mount: open()"); if (fchroot(opt->cur_rootdir_fd)==-1) { - perror("fchroot()"); + perror("secure-mount: fchroot()"); goto err1; } if (fd==-1) goto err0; if (flock(fd, LOCK_EX)==-1) { - perror("flock()"); + perror("secure-mount: flock()"); goto err1; } @@ -284,7 +305,7 @@ updateMtab(struct MountInfo const *mnt, struct Options const *opt) 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; } @@ -307,8 +328,8 @@ 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 && strcmp(mnt->data, "defaults")!=0) { @@ -327,18 +348,18 @@ 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; } @@ -354,7 +375,7 @@ mountSingle(struct MountInfo const *mnt, struct Options const *opt) if (opt->rootdir!=0) { if (chdir(opt->rootdir)==-1) { - perror("chdir()"); + PERROR_Q("secure-mount: chdir", opt->rootdir); return false; } @@ -363,23 +384,23 @@ mountSingle(struct MountInfo const *mnt, struct Options const *opt) if (opt->is_secure) { if (chdirSecure(dir)==-1) { - perror("chdirSecure()"); + PERROR_Q("secure-mount: chdirSecure", dir); return false; } } else { if (*dir!='\0' && chdir(dir)==-1) { - perror("chdir()"); + PERROR_Q("secure-mount: chdir", dir); return false; } } - if (mnt->flags&MS_BIND) { + 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; } } @@ -388,10 +409,10 @@ mountSingle(struct MountInfo const *mnt, struct Options const *opt) } // Check if directories were moved between the chdirSecure() and mount(2) - if ((mnt->flags&MS_BIND) && opt->rootdir!=0 && + if ((mnt->flag&MS_BIND) && opt->rootdir!=0 && (verifyPosition(mnt->src, opt->rootdir, mnt->dst)==-1 || fchroot(opt->cur_rootdir_fd)==-1)) { - perror("verifyPosition/fchroot"); + perror("secure-mount: verifyPosition/fchroot"); // TODO: what is with unmounting? return false; } @@ -405,37 +426,40 @@ 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) { - 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; } @@ -464,10 +488,10 @@ parseFstabLine(struct MountInfo *info, char *buf) if (strcmp(info->type, "swap")==0) return prIGNORE; if (strcmp(info->type, "none")==0) info->type = 0; - info->flags = 0; - info->noauto = false; + info->flag = 0; + info->xflag = 0; if (!transformOptionList(info)) return prFAIL; - if (info->noauto) return prIGNORE; + if (info->xflag & XFLAG_NOAUTO) return prIGNORE; return prDOIT; } @@ -484,14 +508,14 @@ 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); if (len==-1 || lseek(fd, 0, SEEK_SET)==-1) { - perror("lseek()"); + perror("secure-mount: lseek()"); goto err1; } @@ -500,7 +524,7 @@ mountFstab(struct Options const *opt) char *ptr, *ptrptr; if (read(fd, buf, len+1)!=len) { - perror("read()"); + perror("secure-mount: read()"); goto err1; } buf[len] = '#'; // workaround for broken dietlibc strtok_r() @@ -548,9 +572,9 @@ int main(int argc, char *argv[]) .src = 0, .dst = 0, .type = 0, - .flags = 0, + .flag = 0, + .xflag = 0, .data = 0, - .noauto = false }; struct Options opt = { @@ -566,7 +590,7 @@ int main(int argc, char *argv[]) opt.cur_rootdir_fd = open("/", O_RDONLY|O_DIRECTORY); if (opt.cur_rootdir_fd==-1) { - perror("open(\"/\")"); + perror("secure-mount: open(\"/\")"); return EXIT_FAILURE; } @@ -581,9 +605,9 @@ 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_RBIND : mnt.flags |= MS_REC; /*@fallthrough@*/ - 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;