X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fsecure-mount.c;h=1a3bc19c46410d86618a25a17f19a96f96aa22cb;hb=bbb19dac903273aa21a5497c0dc1538cab22200d;hp=b56ff4fe2011a45ef6db48713df7d9964c2e7612;hpb=12b0a4cfbc4834f585a4b71aad2cf03c7de7f94e;p=util-vserver.git diff --git a/src/secure-mount.c b/src/secure-mount.c index b56ff4f..1a3bc19 100644 --- a/src/secure-mount.c +++ b/src/secure-mount.c @@ -52,6 +52,7 @@ #include #include #include +#include #define ENSC_WRAPPERS_FCNTL 1 #define ENSC_WRAPPERS_UNISTD 1 @@ -62,13 +63,15 @@ typedef enum { rfsYES, rfsNO, rfsONLY } RootFsOption; struct MountInfo { - char const * src; - char const * dst; - char const * type; + char * src; + char * dst; + char * name; + char * type; unsigned long flag; unsigned long xflag; unsigned long mask; char * data; + char * data_parsed; }; struct Options { @@ -93,6 +96,7 @@ struct Options { #define OPTION_ROOTFS 1031 #define XFLAG_NOAUTO 0x01 +#define XFLAG_FILE 0x02 static struct option const CMDLINE_OPTIONS[] = { @@ -110,7 +114,19 @@ CMDLINE_OPTIONS[] = { }; #ifndef MS_REC -# define MS_REC 0x4000 +#define MS_REC 0x4000 +#endif +#ifndef MS_UNBINDABLE +#define MS_UNBINDABLE (1<<17) +#endif +#ifndef MS_PRIVATE +#define MS_PRIVATE (1<<18) +#endif +#ifndef MS_SLAVE +#define MS_SLAVE (1<<19) +#endif +#ifndef MS_SHARED +#define MS_SHARED (1<<20) #endif static struct FstabOption { @@ -120,7 +136,7 @@ static struct FstabOption { unsigned long const xflag; bool const is_dflt; } const FSTAB_OPTIONS[] = { - { "defaults", 0, (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC| + { "defaults", MS_NODEV, (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 }, @@ -151,6 +167,11 @@ static struct FstabOption { { "noauto", 0, 0, XFLAG_NOAUTO, false }, { "user", 0, 0, 0, false }, { "nouser", 0, 0, 0, false }, + { "rec", MS_REC, MS_REC, 0, false }, + { "unbindable", MS_UNBINDABLE, MS_UNBINDABLE, 0, false }, + { "private", MS_PRIVATE, MS_PRIVATE, 0, false }, + { "slave", MS_SLAVE, MS_SLAVE, 0, false }, + { "shared", MS_SHARED, MS_SHARED, 0, false }, }; int wrapper_exit_code = 1; @@ -277,14 +298,16 @@ updateMtab(struct MountInfo const *mnt, struct Options const *opt) goto err0; } - if (flock(fd, LOCK_EX)==-1) { - perror("secure-mount: flock()"); + if (lockf(fd, F_LOCK, 0)==-1) { + perror("secure-mount: lockf()"); goto err1; } if (writeStrX(fd, mnt->src)==-1 || writeStrX(fd, " ")==-1 || writeStrX(fd, mnt->dst)==-1 || + writeStrX(fd, mnt->xflag & XFLAG_FILE ? "/" : "")==-1 || + writeStrX(fd, mnt->xflag & XFLAG_FILE ? mnt->name : "")==-1 || writeStrX(fd, " ")==-1 || writeStrX(fd, getType(mnt))==-1 || writeStrX(fd, " ")==-1 || @@ -339,7 +362,7 @@ callExternalMount(struct MountInfo const *mnt) } argv[idx++] = mnt->src; - argv[idx++] = "."; + argv[idx++] = mnt->name; argv[idx] = 0; pid = fork(); @@ -411,6 +434,8 @@ canHandleInternal(struct MountInfo const *mnt) if (!mnt) return false; else if ((mnt->flag & (MS_BIND|MS_MOVE))) return true; + else if ((mnt->flag & (MS_SHARED|MS_SLAVE|MS_PRIVATE| + MS_UNBINDABLE))) return true; else if (mnt->type==0) return false; for (i=FS+0; *i!=0; ++i) @@ -428,12 +453,25 @@ mountSingle(struct MountInfo const *mnt, struct Options const *opt) return false; if (canHandleInternal(mnt)) { - if (mount(mnt->src, ".", + if (mount(mnt->src, mnt->name, mnt->type ? mnt->type : "", - mnt->flag, mnt->data)==-1) { + mnt->flag, mnt->data_parsed)==-1) { perror("secure-mount: mount()"); return false; } + if ((mnt->flag & MS_BIND) && + (mnt->mask & ~(MS_BIND|MS_REC))) { + /* This is needed to put us in the new mountpoint */ + if (!secureChdir(mnt->dst, opt)) + return false; + if (mount(mnt->src, mnt->name, + mnt->type ? mnt->type : "", + (mnt->flag | MS_REMOUNT), NULL) == -1 && + errno != EBUSY) { /* Returned on older kernels */ + perror("secure-mount: mount()"); + return false; + } + } } else if (!callExternalMount(mnt)) return false; @@ -461,6 +499,8 @@ static bool transformOptionList(struct MountInfo *info, size_t UNUSED *col) { char const * ptr = info->data; + char * data = malloc(strlen(info->data)); + char * dst = data; do { char const * pos = strchr(ptr, ','); @@ -475,6 +515,13 @@ transformOptionList(struct MountInfo *info, size_t UNUSED *col) info->mask |= opt->mask; info->xflag |= opt->xflag; } + else { + if (dst != data) + *(dst++) = ','; + strncpy(dst, ptr, pos-ptr); + dst += pos - ptr; + *dst = '\0'; + } if (*pos!='\0') ptr = pos+1; @@ -483,6 +530,7 @@ transformOptionList(struct MountInfo *info, size_t UNUSED *col) } while (*ptr!='\0'); + info->data_parsed = data; return true; } @@ -515,6 +563,7 @@ static enum {prDOIT, prFAIL, prIGNORE} info->flag = MS_NODEV; info->mask = 0; info->xflag = 0; + info->name = "."; if (strcmp(info->type, "swap") ==0) return prIGNORE; else if (strcmp(info->type, "none") ==0) info->type = 0; @@ -545,6 +594,17 @@ showFstabPosition(int fd, char const *fname, size_t line_nr, size_t col_nr) Vwrite(fd, buf, len); } +static void +adjustFileMount(struct MountInfo *mnt) +{ + char *buf = strrchr(mnt->dst, '/'); + + if (buf) + *buf++ = 0; + + mnt->name = buf; + mnt->xflag |= XFLAG_FILE; +} static bool mountFstab(struct Options const *opt) @@ -597,9 +657,13 @@ mountFstab(struct Options const *opt) Echdir("/"); 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"); + else { + if (utilvserver_isFile(mnt.dst, 0)) + adjustFileMount(&mnt); + if (!mountSingle(&mnt, opt)) { + showFstabPosition(2, opt->fstab, line_nr, 1); + WRITE_MSG(2, ": failed to mount fstab-entry\n"); + } } break; } @@ -644,6 +708,7 @@ int main(int argc, char *argv[]) struct MountInfo mnt = { .src = 0, .dst = 0, + .name = ".", .type = 0, .flag = MS_NODEV, .xflag = 0, @@ -685,7 +750,7 @@ int main(int argc, char *argv[]) default : WRITE_MSG(2, "Try '"); WRITE_STR(2, argv[0]); - WRITE_MSG(2, " --help\" for more information.\n"); + WRITE_MSG(2, " --help' for more information.\n"); return EXIT_FAILURE; break; } @@ -721,7 +786,10 @@ int main(int argc, char *argv[]) mnt.src = argv[optind++]; mnt.dst = argv[optind++]; - if (!mountSingle(&mnt, &opt)) return EXIT_FAILURE; + if (utilvserver_isFile(mnt.dst, 0)) + adjustFileMount(&mnt); + if (!mountSingle(&mnt, &opt)) + return EXIT_FAILURE; return EXIT_SUCCESS; }