--- LICENSE | 1 + Makefile | 1 + switch_root.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 138 insertions(+) create mode 100644 switch_root.c diff --git a/LICENSE b/LICENSE index a1078df..91107e6 100644 --- a/LICENSE +++ b/LICENSE _AT_@ -6,6 +6,7 @@ MIT/X Consortium License =C2=A9 2013 Jakob Kramer <jakob.kramer_AT_gmx.de> =C2=A9 2014 Carlos J. Torres <vlaadbrain_AT_gmail.com> =C2=A9 2014 Hiltjo Posthuma <hiltjo_AT_codemadness.org> +=C2=A9 2014 Laslo Hunhold <dev_AT_frign.de> =20 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/Makefile b/Makefile index c139777..0e9d26e 100644 --- a/Makefile +++ b/Makefile _AT_@ -45,6 +45,7 @@ SRC =3D \ su.c \ swapoff.c \ swapon.c \ + switch_root.c \ truncate.c \ umount.c \ unshare.c \ diff --git a/switch_root.c b/switch_root.c new file mode 100644 index 0000000..cfa37e9 --- /dev/null +++ b/switch_root.c _AT_@ -0,0 +1,136 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdio.h> +#include <stdlib.h> +#include <linux/magic.h> +#include <linux/limits.h> +#include <unistd.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/vfs.h> +#include <fcntl.h> +#include <dirent.h> +#include "util.h" + +static void +delete_content(const char *dir, dev_t curdevice){ + char path[PATH_MAX]; + DIR *d; + struct stat st; + struct dirent *dent; +=09 + /* don't dive into other filesystems */ + if (lstat(dir, &st) || st.st_dev !=3D curdevice){ + return; + } + /* delete contents recursively */ + if (S_ISDIR(st.st_mode)) { + d =3D opendir(dir); + if (d) { + for(; (dent =3D readdir(d)) ;) { + /* skip ".." and "." */ + if (dent->d_name[0] =3D=3D '.' + && ((dent->d_name[1] =3D=3D '.' && dent->d_name[2] =3D=3D 0) + || (dent->d_name[1] =3D=3D 0))) + { + continue; + } + =09 + /* build path and dive deeper */ + strlcat(path, dir, sizeof(path)); + strlcat(path, dent->d_name, sizeof(path)); + + delete_content(path, curdevice); + path[0] =3D 0; + } + closedir(d); + =09 + /* remove now empty dir */ + rmdir(dir); + } + } else { + /* unlink non-directory */ + unlink(dir); + } +} + +static void +usage(void) +{ + eprintf("usage: %s [-c console] [newroot] [init] (PID 1)\n", argv0); +} + +int +main(int argc, char **argv) +{ + char *console =3D NULL; + dev_t curdev; + struct stat st; + struct statfs stfs; + + ARGBEGIN { + case 'c': + console =3D EARGF(usage()); + break; + default: + usage(); + } ARGEND; + + /* check number of args and if we are PID 1 */ + if (argc !=3D 2 || getpid() !=3D 1){ + usage(); + } +=09 + /* chdir to newroot and make sure it's a different fs */ + if (chdir(argv[0])) { + eprintf("chdir %s:", argv[0]); + } + if (stat("/", &st)) { + eprintf("stat %s:", "/"); + } + curdev =3D st.st_dev; + if (stat(".", &st)) { + eprintf("stat %s:", "."); + } + if (st.st_dev =3D=3D curdev) { + usage(); + } + + /* further checks */ + if (stat("/init", &st) || !S_ISREG(st.st_mode)) { + /* avoids trouble with real filesystems */ + eprintf("/init is not a regular file\n"); + } + statfs("/", &stfs); + if ((unsigned)stfs.f_type !=3D RAMFS_MAGIC && (unsigned)stfs.f_type !=3D = TMPFS_MAGIC){ + eprintf("current filesystem is not a RAMFS or TMPFS\n"); + } +=09 + /* wipe / */ + delete_content("/", curdev); +=09 + /* overmount / with newroot and chroot into it */ + if (mount(".", "/", NULL, MS_MOVE, NULL)) { + eprintf("mount %s:", "."); + } + if (chroot(".")) { + eprintf("chroot failed\n"); + } + + /* if -c is set, redirect stdin/stdout/stderr to console */ + if (console) { + close(0); + if(open(console, O_RDWR) =3D=3D -1){ + eprintf("open %s:", console); + } + if (dup2(0,1) =3D=3D -1){ + eprintf("dup2 %s:", "0,1"); + } + if (dup2(0,2) =3D=3D -1){ + eprintf("dup2 %s:", "0,2"); + } + } + + /* execute init */ + execv(argv[1], argv); + eprintf("can't execute '%s'\n", argv[1]); +} --=20 1.8.3.2 --Multipart=_Mon__14_Apr_2014_00_15_12_+0200_PFbmMdwa_u.7YJDY--Received on Mon Sep 17 2001 - 00:00:00 CEST
This archive was generated by hypermail 2.3.0 : Mon Apr 14 2014 - 02:36:02 CEST