[Devel] [patch] ext: prevent panic inside of containers
Vasiliy Kulikov
segoon at openwall.com
Mon Jan 24 02:50:35 PST 2011
Hi,
Currently root inside of container may mount crappy ext2/ext3 filesystem
with option errors=panic and cause global HN panic. It can be triggered
with either loop forwarding enabled or any writable block device. E.g.
with loop device:
dd if=/dev/zero of=image bs=1024 count=1024
mkfs.ext2 -F image
head -c 10000 image >image2
mount -o loop,errors=panic image2 /mnt
ls /mnt => kernel panic
The patch forbids setting panic option via both "mount -o" and
in-superblock option inside of containers. Mount option would fail;
in-superblock option would be skipped and default "errors=continue"
would be set. Both event types are logged.
Ideally full emulation should reboot/shutdown container in case of panic'able
error, but it doesn't worth it :-)
Tested on 194.26.1.el5.028stab079.1.
Signed-off-by: Vasiliy Kulikov <segoon at openwall.com>
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 65035cc..3e35dde 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -366,6 +366,7 @@ static int parse_options (char * options,
char * p;
substring_t args[MAX_OPT_ARGS];
int option;
+ struct ve_struct *env;
if (!options)
return 1;
@@ -404,6 +405,12 @@ static int parse_options (char * options,
/* *sb_block = match_int(&args[0]); */
break;
case Opt_err_panic:
+ env = get_exec_env();
+ if (!ve_is_super(env)) {
+ printk(KERN_ERR "EXT2 may not be mounted with "
+ "errors=panic inside of container (VEID=%d)\n", env->veid);
+ return 0;
+ }
clear_opt (sbi->s_mount_opt, ERRORS_CONT);
clear_opt (sbi->s_mount_opt, ERRORS_RO);
set_opt (sbi->s_mount_opt, ERRORS_PANIC);
@@ -651,6 +658,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
int db_count;
int i, j;
__le32 features;
+ struct ve_struct *env = get_exec_env();
sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
@@ -715,9 +723,16 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
#endif
}
- if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
- set_opt(sbi->s_mount_opt, ERRORS_PANIC);
- else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_RO)
+ if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC) {
+ if (!ve_is_super(env)) {
+ printk(KERN_WARNING "EXT2 may not be mounted with "
+ "errors=panic inside of container (VEID=%d), "
+ "ignoring option in superblock.\n", env->veid);
+ set_opt(sbi->s_mount_opt, ERRORS_CONT);
+ } else {
+ set_opt(sbi->s_mount_opt, ERRORS_PANIC);
+ }
+ } else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_RO)
set_opt(sbi->s_mount_opt, ERRORS_RO);
else
set_opt(sbi->s_mount_opt, ERRORS_CONT);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index b15212b..2817f2b 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -792,6 +792,7 @@ static int parse_options (char *options, struct super_block *sb,
int qtype;
char *qname;
#endif
+ struct ve_struct *env;
if (!options)
return 1;
@@ -830,6 +831,12 @@ static int parse_options (char *options, struct super_block *sb,
/* *sb_block = match_int(&args[0]); */
break;
case Opt_err_panic:
+ env = get_exec_env();
+ if (!ve_is_super(env)) {
+ printk(KERN_ERR "EXT3 may not be mounted with "
+ "errors=panic inside of container (VEID=%d)\n", env->veid);
+ return 0;
+ }
clear_opt (sbi->s_mount_opt, ERRORS_CONT);
clear_opt (sbi->s_mount_opt, ERRORS_RO);
set_opt (sbi->s_mount_opt, ERRORS_PANIC);
@@ -1438,6 +1445,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
int i;
int needs_recovery;
__le32 features;
+ struct ve_struct *env = get_exec_env();
sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
@@ -1505,9 +1513,16 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_WBACK)
sbi->s_mount_opt |= EXT3_MOUNT_WRITEBACK_DATA;
- if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_PANIC)
- set_opt(sbi->s_mount_opt, ERRORS_PANIC);
- else if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_RO)
+ if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_PANIC) {
+ if (!ve_is_super(env)) {
+ printk(KERN_WARNING "EXT3 may not be mounted with "
+ "errors=panic inside of container (VEID=%d), "
+ "ignoring option in superblock.\n", env->veid);
+ set_opt(sbi->s_mount_opt, ERRORS_CONT);
+ } else {
+ set_opt(sbi->s_mount_opt, ERRORS_PANIC);
+ }
+ } else if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_RO)
set_opt(sbi->s_mount_opt, ERRORS_RO);
else
set_opt(sbi->s_mount_opt, ERRORS_CONT);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 7e546bc..076b762 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1192,6 +1192,7 @@ static int parse_options(char *options, struct super_block *sb,
int qtype, qfmt;
char *qname;
#endif
+ struct ve_struct *env;
if (!options)
return 1;
@@ -1230,6 +1231,12 @@ static int parse_options(char *options, struct super_block *sb,
/* *sb_block = match_int(&args[0]); */
break;
case Opt_err_panic:
+ env = get_exec_env();
+ if (!ve_is_super(env)) {
+ printk(KERN_ERR "EXT4 may not be mounted with "
+ "errors=panic inside of container (VEID=%d)\n", env->veid);
+ return 0;
+ }
clear_opt(sbi->s_mount_opt, ERRORS_CONT);
clear_opt(sbi->s_mount_opt, ERRORS_RO);
set_opt(sbi->s_mount_opt, ERRORS_PANIC);
@@ -2351,6 +2358,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
__u64 blocks_count;
int err;
unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
+ struct ve_struct *env = get_exec_env();
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
@@ -2435,9 +2443,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_WBACK)
sbi->s_mount_opt |= EXT4_MOUNT_WRITEBACK_DATA;
- if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC)
- set_opt(sbi->s_mount_opt, ERRORS_PANIC);
- else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_CONTINUE)
+ if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC) {
+ if (!ve_is_super(env)) {
+ printk(KERN_WARNING "EXT4 may not be mounted with "
+ "errors=panic inside of container (VEID=%d), "
+ "ignoring option in superblock.\n", env->veid);
+ set_opt(sbi->s_mount_opt, ERRORS_CONT);
+ } else {
+ set_opt(sbi->s_mount_opt, ERRORS_PANIC);
+ }
+ } else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_CONTINUE)
set_opt(sbi->s_mount_opt, ERRORS_CONT);
else
set_opt(sbi->s_mount_opt, ERRORS_RO);
--
Vasiliy Kulikov
http://www.openwall.com - bringing security into open computing environments
More information about the Devel
mailing list