summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c112
1 files changed, 110 insertions, 2 deletions
diff --git a/src/main.c b/src/main.c
index 98daf2c..f609cfa 100644
--- a/src/main.c
+++ b/src/main.c
@@ -9,8 +9,11 @@
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
#include <unistd.h>
/*
@@ -45,9 +48,15 @@ static bool writeProcSelfFile( const char * file, const char * data, size_t size
int main( int argc, char * argv[] )
{
+ int ret;
+
uid_t uid = geteuid();
gid_t gid = getegid();
- unshare( CLONE_NEWUSER | CLONE_NEWNET | CLONE_NEWNS );
+ ret = unshare( CLONE_NEWUSER | CLONE_NEWNET | CLONE_NEWNS );
+ if( ret < 0 ){
+ fprintf( stderr, "unsharing user, network and mount namespaces failed: %s\n", strerror( errno ));
+ return 1;
+ }
char buf[ 256 ];
int len;
@@ -71,7 +80,63 @@ int main( int argc, char * argv[] )
if ( ! writeProcSelfFile( "gid_map", buf, len ) )
return 1;
- mount( "tmpfs", "/run", "tmpfs", 0, "size=4m" );
+ /*
+ * Prepare for future filesystem isolation within additional mount namespace:
+ * - clone whole mount tree as read-only under new /tmp/new_root
+ * - keep writable /proc and /tmp
+ */
+
+ ret = mount( "tmpfs", "/run", "tmpfs", 0, "size=4m" );
+ if( ret < 0 ){
+ fprintf( stderr, "failed to mount tmpfs on /run: %s\n", strerror( errno ));
+ return 1;
+ }
+
+ ret = mkdir( "/run/new_root", 0700 );
+ if( ret < 0 ){
+ fprintf( stderr, "failed to create new_root directory: %s\n", strerror( errno ));
+ return 1;
+ }
+
+ ret = mount( "/", "/run/new_root", NULL, MS_BIND | MS_REC, NULL );
+ if( ret < 0 ){
+ fprintf( stderr, "failed to bind-mount / on new_root: %s\n", strerror( errno ));
+ return 1;
+ }
+
+ struct mount_attr * attr_ro = &( struct mount_attr ) {
+ .attr_set = MOUNT_ATTR_RDONLY,
+ };
+ ret = mount_setattr( -1, "/run/new_root", AT_RECURSIVE, attr_ro, sizeof( * attr_ro ) );
+ if( ret < 0 ){
+ fprintf( stderr, "failed set new_root as read-only: %s\n", strerror( errno ));
+ return 1;
+ }
+
+ struct mount_attr * attr_rw = &( struct mount_attr ) {
+ .attr_clr = MOUNT_ATTR_RDONLY,
+ };
+ ret = mount_setattr( -1, "/run/new_root/proc", AT_RECURSIVE, attr_rw, sizeof( * attr_rw ) );
+ if( ret < 0 ){
+ fprintf( stderr, "failed set new_root/proc as read-write: %s\n", strerror( errno ));
+ return 1;
+ }
+ ret = mount_setattr( -1, "/run/new_root/tmp", AT_RECURSIVE, attr_rw, sizeof( * attr_rw ) );
+ if( ret < 0 ){
+ fprintf( stderr, "failed set new_root/tmp as read-write: %s\n", strerror( errno ));
+ }
+
+ ret = mount( "tmpfs", "/run/new_root/run", "tmpfs", 0, "size=4m" );
+ if( ret < 0 ){
+ fprintf( stderr, "failed to mount tmpfs on new_root/run: %s\n", strerror( errno ));
+ return 1;
+ }
+
+ ret = mkdir( "/run/new_root/run/old_root", 0700 );
+ if( ret < 0 ){
+ fprintf( stderr, "failed to create old_root directory: %s\n", strerror( errno ));
+ return 1;
+ }
hs_init( &argc, &argv );
testerMain();
@@ -79,3 +144,46 @@ int main( int argc, char * argv[] )
return 0;
}
+
+/*
+ * - Replace filesystem hierarchy with read-only version,
+ * - bind-mound rwdir from writable tree, and
+ * - keep writeable /tmp from host.
+ */
+int erebos_tester_isolate_fs( const char * rwdir )
+{
+ int ret;
+
+ ret = unshare( CLONE_NEWNS );
+ if( ret < 0 ){
+ fprintf( stderr, "unsharing mount namespace failed: %s\n", strerror( errno ));
+ return -1;
+ }
+
+ char * cwd = getcwd( NULL, 0 );
+ ret = syscall( SYS_pivot_root, "/run/new_root", "/run/new_root/run/old_root" );
+ if( ret < 0 ){
+ fprintf( stderr, "failed to pivot_root: %s\n", strerror( errno ));
+ free( cwd );
+ return -1;
+ }
+
+ char oldrwdir[ strlen(rwdir) + 15 ];
+ snprintf( oldrwdir, sizeof oldrwdir, "/run/old_root/%s", rwdir );
+ ret = mount( oldrwdir, rwdir, NULL, MS_BIND, NULL );
+ if( ret < 0 ){
+ fprintf( stderr, "failed to bind-mount %s on %s: %s\n", oldrwdir, rwdir, strerror( errno ));
+ free( cwd );
+ return -1;
+ }
+
+ ret = chdir( cwd );
+ if( ret < 0 ){
+ fprintf( stderr, "failed to chdir to %s: %s\n", cwd, strerror( errno ));
+ free( cwd );
+ return -1;
+ }
+ free( cwd );
+
+ return 0;
+}