http://jfs.bkbits.net/linux-2.5
shaggy@austin.ibm.com|ChangeSet|20041201221757|59199 shaggy

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/12/01 16:17:57-06:00 shaggy@austin.ibm.com 
#   JFS: add security and trusted xattrs
#   
#   Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
# 
# fs/jfs/xattr.c
#   2004/12/01 16:17:46-06:00 shaggy@austin.ibm.com +55 -4
#   Add security and trusted xattrs
# 
# fs/Kconfig
#   2004/12/01 16:17:46-06:00 shaggy@austin.ibm.com +12 -0
#   Add jfs security labels (xattrs)
# 
# ChangeSet
#   2004/11/17 12:51:43-06:00 shaggy@austin.ibm.com 
#   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 <shaggy@austin.ibm.com>
# 
# fs/jfs/inode.c
#   2004/11/17 12:51:26-06:00 shaggy@austin.ibm.com +8 -3
#   jfs_commit_inode needs to re-verify that inode is still linked
#   and dirty
# 
diff -Nru a/fs/Kconfig b/fs/Kconfig
--- a/fs/Kconfig	2004-12-12 18:20:49 -08:00
+++ b/fs/Kconfig	2004-12-12 18:20:49 -08:00
@@ -266,6 +266,18 @@
 
 	  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 -Nru a/fs/jfs/inode.c b/fs/jfs/inode.c
--- a/fs/jfs/inode.c	2004-12-12 18:20:49 -08:00
+++ b/fs/jfs/inode.c	2004-12-12 18:20:49 -08:00
@@ -81,8 +81,7 @@
 	 * 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 @@
 
 	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;
diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c
--- a/fs/jfs/xattr.c	2004-12-12 18:20:49 -08:00
+++ b/fs/jfs/xattr.c	2004-12-12 18:20:49 -08:00
@@ -91,6 +91,12 @@
 #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,
@@ -111,6 +117,19 @@
 	    !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 @@
 		 */
 		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 @@
 
 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 @@
 	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 @@
 	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 @@
 	/* 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:
