aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorDr. Tilmann Bubeck <t.bubeck@reinform.de>2013-04-08 12:54:05 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-04-08 12:54:05 -0400
commit393d1d1d76933886d5e1ce603214c9987589c6d5 (patch)
tree2f2368a9d787ccb8e69f61a3e5023ef9c4abfd8b /fs/ext4/inode.c
parentf78ee70db40040e6f38a5134527d4760254d6683 (diff)
ext4: implementation of a new ioctl called EXT4_IOC_SWAP_BOOT
Add a new ioctl, EXT4_IOC_SWAP_BOOT which swaps i_blocks and associated attributes (like i_blocks, i_size, i_flags, ...) from the specified inode with inode EXT4_BOOT_LOADER_INO (#5). This is typically used to store a boot loader in a secure part of the filesystem, where it can't be changed by a normal user by accident. The data blocks of the previous boot loader will be associated with the given inode. This usercode program is a simple example of the usage: int main(int argc, char *argv[]) { int fd; int err; if ( argc != 2 ) { printf("usage: ext4-swap-boot-inode FILE-TO-SWAP\n"); exit(1); } fd = open(argv[1], O_WRONLY); if ( fd < 0 ) { perror("open"); exit(1); } err = ioctl(fd, EXT4_IOC_SWAP_BOOT); if ( err < 0 ) { perror("ioctl"); exit(1); } close(fd); exit(0); } [ Modified by Theodore Ts'o to fix a number of bugs in the original code.] Signed-off-by: Dr. Tilmann Bubeck <t.bubeck@reinform.de> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 769c656ea3b1..a29bfc2142ef 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4191,8 +4191,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
4191 * NeilBrown 1999oct15 4191 * NeilBrown 1999oct15
4192 */ 4192 */
4193 if (inode->i_nlink == 0) { 4193 if (inode->i_nlink == 0) {
4194 if (inode->i_mode == 0 || 4194 if ((inode->i_mode == 0 ||
4195 !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { 4195 !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) &&
4196 ino != EXT4_BOOT_LOADER_INO) {
4196 /* this inode is deleted */ 4197 /* this inode is deleted */
4197 ret = -ESTALE; 4198 ret = -ESTALE;
4198 goto bad_inode; 4199 goto bad_inode;
@@ -4200,7 +4201,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
4200 /* The only unlinked inodes we let through here have 4201 /* The only unlinked inodes we let through here have
4201 * valid i_mode and are being read by the orphan 4202 * valid i_mode and are being read by the orphan
4202 * recovery code: that's fine, we're about to complete 4203 * recovery code: that's fine, we're about to complete
4203 * the process of deleting those. */ 4204 * the process of deleting those.
4205 * OR it is the EXT4_BOOT_LOADER_INO which is
4206 * not initialized on a new filesystem. */
4204 } 4207 }
4205 ei->i_flags = le32_to_cpu(raw_inode->i_flags); 4208 ei->i_flags = le32_to_cpu(raw_inode->i_flags);
4206 inode->i_blocks = ext4_inode_blocks(raw_inode, ei); 4209 inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
@@ -4320,6 +4323,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
4320 else 4323 else
4321 init_special_inode(inode, inode->i_mode, 4324 init_special_inode(inode, inode->i_mode,
4322 new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); 4325 new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
4326 } else if (ino == EXT4_BOOT_LOADER_INO) {
4327 make_bad_inode(inode);
4323 } else { 4328 } else {
4324 ret = -EIO; 4329 ret = -EIO;
4325 EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode); 4330 EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode);