From 00746b1f2a432f8b0a338414fc2c7b4d5266f150 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Wed, 17 Nov 2004 00:51:43 -0600 Subject: JFS: fix race in jfs_commit_inode There was a race that resulted in old, deleted inodes being written to disk after the inode number had been reused. jfs_commit_inode needs to verify that the inode is still linked and dirty before committing it. Signed-off-by: Dave Kleikamp --- fs/jfs/inode.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index d94abccb9fb1..69e397ef94f6 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -81,8 +81,7 @@ int jfs_commit_inode(struct inode *inode, int wait) * Don't commit if inode has been committed since last being * marked dirty, or if it has been deleted. */ - if (test_cflag(COMMIT_Nolink, inode) || - !test_cflag(COMMIT_Dirty, inode)) + if (inode->i_nlink == 0 || !test_cflag(COMMIT_Dirty, inode)) return 0; if (isReadOnly(inode)) { @@ -100,7 +99,13 @@ int jfs_commit_inode(struct inode *inode, int wait) tid = txBegin(inode->i_sb, COMMIT_INODE); down(&JFS_IP(inode)->commit_sem); - rc = txCommit(tid, 1, &inode, wait ? COMMIT_SYNC : 0); + + /* + * Retest inode state after taking commit_sem + */ + if (inode->i_nlink && test_cflag(COMMIT_Dirty, inode)) + rc = txCommit(tid, 1, &inode, wait ? COMMIT_SYNC : 0); + txEnd(tid); up(&JFS_IP(inode)->commit_sem); return rc; -- cgit v1.2.3 From d6828b1963700ea97367a36d1a5d7a9c38a1a110 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Wed, 1 Dec 2004 04:17:57 -0600 Subject: JFS: add security and trusted xattrs Signed-off-by: Dave Kleikamp --- fs/Kconfig | 12 ++++++++++++ fs/jfs/xattr.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/fs/Kconfig b/fs/Kconfig index cd6ca6da9119..65fa5d3851fe 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -266,6 +266,18 @@ config JFS_POSIX_ACL If you don't know what Access Control Lists are, say N +config JFS_SECURITY + bool "JFS Security Labels" + depends on JFS_FS + help + Security labels support alternative access control models + implemented by security modules like SELinux. This option + enables an extended attribute handler for file security + labels in the jfs filesystem. + + If you are not using a security module that requires using + extended attributes for file security labels, say N. + config JFS_DEBUG bool "JFS debugging" depends on JFS_FS diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 9c0e3a524e9b..7a9ffd5d03dc 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -91,6 +91,12 @@ struct ea_buffer { #define XATTR_OS2_PREFIX "os2." #define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1) +/* XATTR_SECURITY_PREFIX is defined in include/linux/xattr.h */ +#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1) + +#define XATTR_TRUSTED_PREFIX "trusted." +#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1) + /* * These three routines are used to recognize on-disk extended attributes * that are in a recognized namespace. If the attribute is not recognized, @@ -110,6 +116,19 @@ static inline int is_os2_xattr(struct jfs_ea *ea) if ((ea->namelen >= XATTR_USER_PREFIX_LEN) && !strncmp(ea->name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) return FALSE; + /* + * Check for "security." + */ + if ((ea->namelen >= XATTR_SECURITY_PREFIX_LEN) && + !strncmp(ea->name, XATTR_SECURITY_PREFIX, + XATTR_SECURITY_PREFIX_LEN)) + return FALSE; + /* + * Check for "trusted." + */ + if ((ea->namelen >= XATTR_TRUSTED_PREFIX_LEN) && + !strncmp(ea->name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) + return FALSE; /* * Add any other valid namespace prefixes here */ @@ -770,6 +789,15 @@ static int can_set_xattr(struct inode *inode, const char *name, */ return can_set_system_xattr(inode, name, value, value_len); + if(strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) != 0) + return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); + +#ifdef CONFIG_JFS_SECURITY + if (strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) + != 0) + return 0; /* Leave it to the security module */ +#endif + if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) && (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0)) return -EOPNOTSUPP; @@ -937,8 +965,17 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, static int can_get_xattr(struct inode *inode, const char *name) { +#ifdef CONFIG_JFS_SECURITY + if(strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) + return 0; +#endif + + if(strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) + return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); + if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0) return 0; + return permission(inode, MAY_READ, NULL); } @@ -1021,6 +1058,16 @@ ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data, return err; } +/* + * No special permissions are needed to list attributes except for trusted.* + */ +static inline int can_list(struct jfs_ea *ea) +{ + return (strncmp(ea->name, XATTR_TRUSTED_PREFIX, + XATTR_TRUSTED_PREFIX_LEN) || + capable(CAP_SYS_ADMIN)); +} + ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) { struct inode *inode = dentry->d_inode; @@ -1045,8 +1092,10 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) ealist = (struct jfs_ea_list *) ea_buf.xattr; /* compute required size of list */ - for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) - size += name_size(ea) + 1; + for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) { + if (can_list(ea)) + size += name_size(ea) + 1; + } if (!data) goto release; @@ -1059,8 +1108,10 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) /* Copy attribute names to buffer */ buffer = data; for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) { - int namelen = copy_name(buffer, ea); - buffer += namelen + 1; + if (can_list(ea)) { + int namelen = copy_name(buffer, ea); + buffer += namelen + 1; + } } release: -- cgit v1.2.3 From 36b1097211f7198cbd00692695553b1a2a11a1ea Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Thu, 2 Dec 2004 04:45:38 -0600 Subject: JFS: speed up nointegrity mount No need to flush metadata to advance the journal's sync-point if we're not really writing to the journal Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_logmgr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 5573e52a392d..b9e502f4acab 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -980,11 +980,15 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) * actually make it to disk */ list_for_each_entry(sbi, &log->sb_list, log_list) { + if (sbi->flag & JFS_NOINTEGRITY) + continue; filemap_fdatawrite(sbi->ipbmap->i_mapping); filemap_fdatawrite(sbi->ipimap->i_mapping); filemap_fdatawrite(sbi->sb->s_bdev->bd_inode->i_mapping); } list_for_each_entry(sbi, &log->sb_list, log_list) { + if (sbi->flag & JFS_NOINTEGRITY) + continue; filemap_fdatawait(sbi->ipbmap->i_mapping); filemap_fdatawait(sbi->ipimap->i_mapping); filemap_fdatawait(sbi->sb->s_bdev->bd_inode->i_mapping); -- cgit v1.2.3 From c4ede41855dc115348f51c1d3364905e2157831b Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Tue, 7 Dec 2004 03:38:26 -0600 Subject: JFS: flush new iag from bd_inode's mapping This is a fix to help jfs work with grub. A new IAG is created in the bd_inode's mapping, but subsequently modified in a different mapping. We should invalidate the former page to keep grub from using that cached page. It isn't useful to have it cached anyway, since jfs will never access it again through that mapping. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_imap.c | 6 ++++++ fs/jfs/jfs_metapage.c | 9 +-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 9ccb88423066..783831301625 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -2604,6 +2604,12 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) for (i = 0; i < SMAPSZ; i++) iagp->inosmap[i] = cpu_to_le32(ONES); + /* + * Invalidate the page after writing and syncing it. + * After it's initialized, we access it in a different + * address space + */ + set_bit(META_discard, &mp->flag); flush_metapage(mp); /* diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 4420ba1398fb..c6fb317f5ab8 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -396,14 +396,6 @@ static void __write_metapage(struct metapage * mp) jfs_info("__write_metapage: mp = 0x%p", mp); - if (test_bit(META_discard, &mp->flag)) { - /* - * This metadata is no longer valid - */ - clear_bit(META_dirty, &mp->flag); - return; - } - page_index = mp->page->index; page_offset = (mp->index - (page_index << l2BlocksPerPage)) << l2bsize; @@ -549,6 +541,7 @@ again: goto again; } + clear_bit(META_dirty, &mp->flag); set_bit(META_discard, &mp->flag); spin_unlock(&meta_lock); } else { -- cgit v1.2.3 From b4895584897bcbf265f70f87f15097b2ba4b3b13 Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Tue, 28 Dec 2004 22:25:36 -0600 Subject: JFS: delete unused file Remove nowhere referenced file. (egrep "filename\." didn't find anything) Signed-off-by: Domen Puncer Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_defragfs.h | 51 --------------------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 fs/jfs/jfs_defragfs.h diff --git a/fs/jfs/jfs_defragfs.h b/fs/jfs/jfs_defragfs.h deleted file mode 100644 index 3f94820b1e6c..000000000000 --- a/fs/jfs/jfs_defragfs.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2000-2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _H_JFS_DEFRAGFS -#define _H_JFS_DEFRAGFS - -/* - * defragfs parameter list - */ -struct defragfs { - uint flag; /* 4: */ - u8 dev; /* 1: */ - u8 pad[3]; /* 3: */ - s32 fileset; /* 4: */ - u32 inostamp; /* 4: */ - u32 ino; /* 4: */ - u32 gen; /* 4: */ - s64 xoff; /* 8: */ - s64 old_xaddr; /* 8: */ - s64 new_xaddr; /* 8: */ - s32 xlen; /* 4: */ -}; - -/* plist flag */ -#define DEFRAGFS_SYNC 0x80000000 -#define DEFRAGFS_COMMIT 0x40000000 -#define DEFRAGFS_RELOCATE 0x10000000 - -#define INODE_TYPE 0x0000F000 /* IFREG or IFDIR */ - -#define EXTENT_TYPE 0x000000ff -#define DTPAGE 0x00000001 -#define XTPAGE 0x00000002 -#define DATAEXT 0x00000004 -#define EAEXT 0x00000008 - -#endif /* _H_JFS_DEFRAGFS */ -- cgit v1.2.3