linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [AppArmor 00/45] AppArmor security module overview
@ 2007-05-14 11:06 jjohansen
  2007-05-14 11:06 ` [AppArmor 01/45] Pass struct vfsmount to the inode_create LSM hook jjohansen
                   ` (45 more replies)
  0 siblings, 46 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-security-module, linux-fsdevel

lkml-explanatory.txt

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 01/45] Pass struct vfsmount to the inode_create LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 02/45] Pass struct path down to remove_suid and children jjohansen
                   ` (44 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-create.diff --]
[-- Type: text/plain, Size: 3186 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/namei.c               |    2 +-
 include/linux/security.h |    9 ++++++---
 security/dummy.c         |    2 +-
 security/selinux/hooks.c |    3 ++-
 4 files changed, 10 insertions(+), 6 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1521,7 +1521,7 @@ int vfs_create(struct inode *dir, struct
 		return -EACCES;	/* shouldn't it be ENOSYS? */
 	mode &= S_IALLUGO;
 	mode |= S_IFREG;
-	error = security_inode_create(dir, dentry, mode);
+	error = security_inode_create(dir, dentry, nd ? nd->mnt : NULL, mode);
 	if (error)
 		return error;
 	DQUOT_INIT(dir);
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -283,6 +283,7 @@ struct request_sock;
  *	Check permission to create a regular file.
  *	@dir contains inode structure of the parent of the new file.
  *	@dentry contains the dentry structure for the file to be created.
+ *	@mnt is the vfsmount corresponding to @dentry (may be NULL).
  *	@mode contains the file mode of the file to be created.
  *	Return 0 if permission is granted.
  * @inode_link:
@@ -1204,8 +1205,8 @@ struct security_operations {
 	void (*inode_free_security) (struct inode *inode);
 	int (*inode_init_security) (struct inode *inode, struct inode *dir,
 				    char **name, void **value, size_t *len);
-	int (*inode_create) (struct inode *dir,
-	                     struct dentry *dentry, int mode);
+	int (*inode_create) (struct inode *dir, struct dentry *dentry,
+			     struct vfsmount *mnt, int mode);
 	int (*inode_link) (struct dentry *old_dentry,
 	                   struct inode *dir, struct dentry *new_dentry);
 	int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
@@ -1611,11 +1612,12 @@ static inline int security_inode_init_se
 	
 static inline int security_inode_create (struct inode *dir,
 					 struct dentry *dentry,
+					 struct vfsmount *mnt,
 					 int mode)
 {
 	if (unlikely (IS_PRIVATE (dir)))
 		return 0;
-	return security_ops->inode_create (dir, dentry, mode);
+	return security_ops->inode_create (dir, dentry, mnt, mode);
 }
 
 static inline int security_inode_link (struct dentry *old_dentry,
@@ -2338,6 +2340,7 @@ static inline int security_inode_init_se
 	
 static inline int security_inode_create (struct inode *dir,
 					 struct dentry *dentry,
+					 struct vfsmount *mnt,
 					 int mode)
 {
 	return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -265,7 +265,7 @@ static int dummy_inode_init_security (st
 }
 
 static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
-			       int mask)
+			       struct vfsmount *mnt, int mask)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2176,7 +2176,8 @@ static int selinux_inode_init_security(s
 	return 0;
 }
 
-static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
+static int selinux_inode_create(struct inode *dir, struct dentry *dentry,
+				 struct vfsmount *mnt, int mask)
 {
 	return may_create(dir, dentry, SECCLASS_FILE);
 }

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 02/45] Pass struct path down to remove_suid and children
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
  2007-05-14 11:06 ` [AppArmor 01/45] Pass struct vfsmount to the inode_create LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 03/45] Add a vfsmount parameter to notify_change() jjohansen
                   ` (43 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: remove_suid.diff --]
[-- Type: text/plain, Size: 4022 bytes --]

Required by a later patch that adds a struct vfsmount parameter to
notify_change().

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/ntfs/file.c             |    2 +-
 fs/reiserfs/file.c         |    2 +-
 fs/splice.c                |    4 ++--
 fs/xfs/linux-2.6/xfs_lrw.c |    2 +-
 include/linux/fs.h         |    4 ++--
 mm/filemap.c               |   12 ++++++------
 mm/filemap_xip.c           |    2 +-
 mm/shmem.c                 |    2 +-
 8 files changed, 15 insertions(+), 15 deletions(-)

--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2121,7 +2121,7 @@ static ssize_t ntfs_file_aio_write_noloc
 		goto out;
 	if (!count)
 		goto out;
-	err = remove_suid(file->f_path.dentry);
+	err = remove_suid(&file->f_path);
 	if (err)
 		goto out;
 	file_update_time(file);
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1335,7 +1335,7 @@ static ssize_t reiserfs_file_write(struc
 	if (count == 0)
 		goto out;
 
-	res = remove_suid(file->f_path.dentry);
+	res = remove_suid(&file->f_path);
 	if (res)
 		goto out;
 
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -796,7 +796,7 @@ generic_file_splice_write_nolock(struct 
 	ssize_t ret;
 	int err;
 
-	err = remove_suid(out->f_path.dentry);
+	err = remove_suid(&out->f_path);
 	if (unlikely(err))
 		return err;
 
@@ -845,7 +845,7 @@ generic_file_splice_write(struct pipe_in
 	err = should_remove_suid(out->f_path.dentry);
 	if (unlikely(err)) {
 		mutex_lock(&inode->i_mutex);
-		err = __remove_suid(out->f_path.dentry, err);
+		err = __remove_suid(&out->f_path, err);
 		mutex_unlock(&inode->i_mutex);
 		if (err)
 			return err;
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -798,7 +798,7 @@ start:
 	     !capable(CAP_FSETID)) {
 		error = xfs_write_clear_setuid(xip);
 		if (likely(!error))
-			error = -remove_suid(file->f_path.dentry);
+			error = -remove_suid(&file->f_path);
 		if (unlikely(error)) {
 			goto out_unlock_internal;
 		}
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1697,9 +1697,9 @@ extern void __iget(struct inode * inode)
 extern void clear_inode(struct inode *);
 extern void destroy_inode(struct inode *);
 extern struct inode *new_inode(struct super_block *);
-extern int __remove_suid(struct dentry *, int);
+extern int __remove_suid(struct path *, int);
 extern int should_remove_suid(struct dentry *);
-extern int remove_suid(struct dentry *);
+extern int remove_suid(struct path *);
 
 extern void __insert_inode_hash(struct inode *, unsigned long hashval);
 extern void remove_inode_hash(struct inode *);
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1905,20 +1905,20 @@ int should_remove_suid(struct dentry *de
 }
 EXPORT_SYMBOL(should_remove_suid);
 
-int __remove_suid(struct dentry *dentry, int kill)
+int __remove_suid(struct path *path, int kill)
 {
 	struct iattr newattrs;
 
 	newattrs.ia_valid = ATTR_FORCE | kill;
-	return notify_change(dentry, &newattrs);
+	return notify_change(path->dentry, &newattrs);
 }
 
-int remove_suid(struct dentry *dentry)
+int remove_suid(struct path *path)
 {
-	int kill = should_remove_suid(dentry);
+	int kill = should_remove_suid(path->dentry);
 
 	if (unlikely(kill))
-		return __remove_suid(dentry, kill);
+		return __remove_suid(path, kill);
 
 	return 0;
 }
@@ -2269,7 +2269,7 @@ __generic_file_aio_write_nolock(struct k
 	if (count == 0)
 		goto out;
 
-	err = remove_suid(file->f_path.dentry);
+	err = remove_suid(&file->f_path);
 	if (err)
 		goto out;
 
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -405,7 +405,7 @@ xip_file_write(struct file *filp, const 
 	if (count == 0)
 		goto out_backing;
 
-	ret = remove_suid(filp->f_path.dentry);
+	ret = remove_suid(&filp->f_path);
 	if (ret)
 		goto out_backing;
 
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1516,7 +1516,7 @@ shmem_file_write(struct file *file, cons
 	if (err || !count)
 		goto out;
 
-	err = remove_suid(file->f_path.dentry);
+	err = remove_suid(&file->f_path);
 	if (err)
 		goto out;
 

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 03/45] Add a vfsmount parameter to notify_change()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
  2007-05-14 11:06 ` [AppArmor 01/45] Pass struct vfsmount to the inode_create LSM hook jjohansen
  2007-05-14 11:06 ` [AppArmor 02/45] Pass struct path down to remove_suid and children jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 04/45] Pass struct vfsmount to the inode_setattr LSM hook jjohansen
                   ` (42 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-notify_change.diff --]
[-- Type: text/plain, Size: 12053 bytes --]

The vfsmount parameter must be set appropriately for files visibile
outside the kernel. Files that are only used in a filesystem (e.g.,
reiserfs xattr files) will have a NULL vfsmount.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/attr.c           |    3 ++-
 fs/ecryptfs/inode.c |    4 +++-
 fs/exec.c           |    3 ++-
 fs/fat/file.c       |    2 +-
 fs/hpfs/namei.c     |    2 +-
 fs/namei.c          |    3 ++-
 fs/nfsd/vfs.c       |    8 ++++----
 fs/open.c           |   28 +++++++++++++++-------------
 fs/reiserfs/xattr.c |    6 +++---
 fs/sysfs/file.c     |    2 +-
 fs/utimes.c         |   11 ++++++-----
 include/linux/fs.h  |    6 +++---
 mm/filemap.c        |    2 +-
 mm/tiny-shmem.c     |    2 +-
 14 files changed, 45 insertions(+), 37 deletions(-)

--- a/fs/attr.c
+++ b/fs/attr.c
@@ -100,7 +100,8 @@ int inode_setattr(struct inode * inode, 
 }
 EXPORT_SYMBOL(inode_setattr);
 
-int notify_change(struct dentry * dentry, struct iattr * attr)
+int notify_change(struct dentry *dentry, struct vfsmount *mnt,
+		  struct iattr *attr)
 {
 	struct inode *inode = dentry->d_inode;
 	mode_t mode;
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -870,12 +870,14 @@ static int ecryptfs_setattr(struct dentr
 {
 	int rc = 0;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct inode *inode;
 	struct inode *lower_inode;
 	struct ecryptfs_crypt_stat *crypt_stat;
 
 	crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
+	lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
 	inode = dentry->d_inode;
 	lower_inode = ecryptfs_inode_to_lower(inode);
 	if (ia->ia_valid & ATTR_SIZE) {
@@ -890,7 +892,7 @@ static int ecryptfs_setattr(struct dentr
 		if (rc < 0)
 			goto out;
 	}
-	rc = notify_change(lower_dentry, ia);
+	rc = notify_change(lower_dentry, lower_mnt, ia);
 out:
 	fsstack_copy_attr_all(inode, lower_inode, NULL);
 	return rc;
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1564,7 +1564,8 @@ int do_coredump(long signr, int exit_cod
 		goto close_fail;
 	if (!file->f_op->write)
 		goto close_fail;
-	if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
+	if (!ispipe &&
+	    do_truncate(file->f_path.dentry, file->f_path.mnt, 0, 0, file) != 0)
 		goto close_fail;
 
 	retval = binfmt->core_dump(signr, regs, file);
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -92,7 +92,7 @@ int fat_generic_ioctl(struct inode *inod
 		}
 
 		/* This MUST be done before doing anything irreversible... */
-		err = notify_change(filp->f_path.dentry, &ia);
+		err = notify_change(filp->f_path.dentry, filp->f_path.mnt, &ia);
 		if (err)
 			goto up;
 
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -426,7 +426,7 @@ again:
 			/*printk("HPFS: truncating file before delete.\n");*/
 			newattrs.ia_size = 0;
 			newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-			err = notify_change(dentry, &newattrs);
+			err = notify_change(dentry, NULL, &newattrs);
 			put_write_access(inode);
 			if (!err)
 				goto again;
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1598,7 +1598,8 @@ int may_open(struct nameidata *nd, int a
 		if (!error) {
 			DQUOT_INIT(inode);
 			
-			error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL);
+			error = do_truncate(dentry, nd->mnt, 0,
+					    ATTR_MTIME|ATTR_CTIME, NULL);
 		}
 		put_write_access(inode);
 		if (error)
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -358,7 +358,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str
 	err = nfserr_notsync;
 	if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
 		fh_lock(fhp);
-		host_err = notify_change(dentry, iap);
+		host_err = notify_change(dentry, fhp->fh_export->ex_mnt, iap);
 		err = nfserrno(host_err);
 		fh_unlock(fhp);
 	}
@@ -893,13 +893,13 @@ out:
 	return err;
 }
 
-static void kill_suid(struct dentry *dentry)
+static void kill_suid(struct dentry *dentry, struct vfsmount *mnt)
 {
 	struct iattr	ia;
 	ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
 
 	mutex_lock(&dentry->d_inode->i_mutex);
-	notify_change(dentry, &ia);
+	notify_change(dentry, mnt, &ia);
 	mutex_unlock(&dentry->d_inode->i_mutex);
 }
 
@@ -958,7 +958,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
 
 	/* clear setuid/setgid flag after write */
 	if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
-		kill_suid(dentry);
+		kill_suid(dentry, exp->ex_mnt);
 
 	if (host_err >= 0 && stable) {
 		static ino_t	last_ino;
--- a/fs/open.c
+++ b/fs/open.c
@@ -193,8 +193,8 @@ out:
 	return error;
 }
 
-int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
-	struct file *filp)
+int do_truncate(struct dentry *dentry, struct vfsmount *mnt, loff_t length,
+		unsigned int time_attrs, struct file *filp)
 {
 	int err;
 	struct iattr newattrs;
@@ -214,7 +214,7 @@ int do_truncate(struct dentry *dentry, l
 	newattrs.ia_valid |= should_remove_suid(dentry);
 
 	mutex_lock(&dentry->d_inode->i_mutex);
-	err = notify_change(dentry, &newattrs);
+	err = notify_change(dentry, mnt, &newattrs);
 	mutex_unlock(&dentry->d_inode->i_mutex);
 	return err;
 }
@@ -269,7 +269,7 @@ static long do_sys_truncate(const char _
 	error = locks_verify_truncate(inode, NULL, length);
 	if (!error) {
 		DQUOT_INIT(inode);
-		error = do_truncate(nd.dentry, length, 0, NULL);
+		error = do_truncate(nd.dentry, nd.mnt, length, 0, NULL);
 	}
 	put_write_access(inode);
 
@@ -321,7 +321,8 @@ static long do_sys_ftruncate(unsigned in
 
 	error = locks_verify_truncate(inode, file, length);
 	if (!error)
-		error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
+		error = do_truncate(dentry, file->f_path.mnt, length,
+				    ATTR_MTIME|ATTR_CTIME, file);
 out_putf:
 	fput(file);
 out:
@@ -521,7 +522,7 @@ asmlinkage long sys_fchmod(unsigned int 
 		mode = inode->i_mode;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-	err = notify_change(dentry, &newattrs);
+	err = notify_change(dentry, file->f_path.mnt, &newattrs);
 	mutex_unlock(&inode->i_mutex);
 
 out_putf:
@@ -556,7 +557,7 @@ asmlinkage long sys_fchmodat(int dfd, co
 		mode = inode->i_mode;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-	error = notify_change(nd.dentry, &newattrs);
+	error = notify_change(nd.dentry, nd.mnt, &newattrs);
 	mutex_unlock(&inode->i_mutex);
 
 dput_and_out:
@@ -570,7 +571,8 @@ asmlinkage long sys_chmod(const char __u
 	return sys_fchmodat(AT_FDCWD, filename, mode);
 }
 
-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
+			uid_t user, gid_t group)
 {
 	struct inode * inode;
 	int error;
@@ -599,7 +601,7 @@ static int chown_common(struct dentry * 
 	if (!S_ISDIR(inode->i_mode))
 		newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID;
 	mutex_lock(&inode->i_mutex);
-	error = notify_change(dentry, &newattrs);
+	error = notify_change(dentry, mnt, &newattrs);
 	mutex_unlock(&inode->i_mutex);
 out:
 	return error;
@@ -613,7 +615,7 @@ asmlinkage long sys_chown(const char __u
 	error = user_path_walk(filename, &nd);
 	if (error)
 		goto out;
-	error = chown_common(nd.dentry, user, group);
+	error = chown_common(nd.dentry, nd.mnt, user, group);
 	path_release(&nd);
 out:
 	return error;
@@ -633,7 +635,7 @@ asmlinkage long sys_fchownat(int dfd, co
 	error = __user_walk_fd(dfd, filename, follow, &nd);
 	if (error)
 		goto out;
-	error = chown_common(nd.dentry, user, group);
+	error = chown_common(nd.dentry, nd.mnt, user, group);
 	path_release(&nd);
 out:
 	return error;
@@ -647,7 +649,7 @@ asmlinkage long sys_lchown(const char __
 	error = user_path_walk_link(filename, &nd);
 	if (error)
 		goto out;
-	error = chown_common(nd.dentry, user, group);
+	error = chown_common(nd.dentry, nd.mnt, user, group);
 	path_release(&nd);
 out:
 	return error;
@@ -666,7 +668,7 @@ asmlinkage long sys_fchown(unsigned int 
 
 	dentry = file->f_path.dentry;
 	audit_inode(NULL, dentry->d_inode);
-	error = chown_common(dentry, user, group);
+	error = chown_common(dentry, file->f_path.mnt, user, group);
 	fput(file);
 out:
 	return error;
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -479,7 +479,7 @@ reiserfs_xattr_set(struct inode *inode, 
 	newattrs.ia_size = buffer_size;
 	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
 	mutex_lock(&xinode->i_mutex);
-	err = notify_change(fp->f_path.dentry, &newattrs);
+	err = notify_change(fp->f_path.dentry, NULL, &newattrs);
 	if (err)
 		goto out_filp;
 
@@ -819,7 +819,7 @@ reiserfs_chown_xattrs_filler(void *buf, 
 	}
 
 	if (!S_ISDIR(xafile->d_inode->i_mode))
-		err = notify_change(xafile, attrs);
+		err = notify_change(xafile, NULL, attrs);
 	dput(xafile);
 
 	return err;
@@ -871,7 +871,7 @@ int reiserfs_chown_xattrs(struct inode *
 		goto out_dir;
 	}
 
-	err = notify_change(dir, attrs);
+	err = notify_change(dir, NULL, attrs);
 	unlock_kernel();
 
       out_dir:
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -554,7 +554,7 @@ int sysfs_chmod_file(struct kobject *kob
 			newattrs.ia_mode = (mode & S_IALLUGO) |
 						(inode->i_mode & ~S_IALLUGO);
 			newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-			res = notify_change(victim, &newattrs);
+			res = notify_change(victim, NULL, &newattrs);
 			mutex_unlock(&inode->i_mutex);
 		}
 		dput(victim);
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -46,7 +46,7 @@ long do_utimes(int dfd, char __user *fil
 {
 	int error;
 	struct nameidata nd;
-	struct dentry *dentry;
+	struct path path;
 	struct inode *inode;
 	struct iattr newattrs;
 	struct file *f = NULL;
@@ -64,16 +64,17 @@ long do_utimes(int dfd, char __user *fil
 		f = fget(dfd);
 		if (!f)
 			goto out;
-		dentry = f->f_path.dentry;
+		path = f->f_path;
 	} else {
 		error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
 		if (error)
 			goto out;
 
-		dentry = nd.dentry;
+		path.dentry = nd.dentry;
+		path.mnt = nd.mnt;
 	}
 
-	inode = dentry->d_inode;
+	inode = path.dentry->d_inode;
 
 	error = -EROFS;
 	if (IS_RDONLY(inode))
@@ -111,7 +112,7 @@ long do_utimes(int dfd, char __user *fil
 			goto dput_and_out;
 	}
 	mutex_lock(&inode->i_mutex);
-	error = notify_change(dentry, &newattrs);
+	error = notify_change(path.dentry, path.mnt, &newattrs);
 	mutex_unlock(&inode->i_mutex);
 dput_and_out:
 	if (f)
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1470,8 +1470,8 @@ static inline int break_lease(struct ino
 
 /* fs/open.c */
 
-extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
-		       struct file *filp);
+extern int do_truncate(struct dentry *, struct vfsmount *, loff_t start,
+		       unsigned int time_attrs, struct file *filp);
 extern long do_sys_open(int fdf, const char __user *filename, int flags,
 			int mode);
 extern struct file *filp_open(const char *, int, int);
@@ -1624,7 +1624,7 @@ extern int do_remount_sb(struct super_bl
 #ifdef CONFIG_BLOCK
 extern sector_t bmap(struct inode *, sector_t);
 #endif
-extern int notify_change(struct dentry *, struct iattr *);
+extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
 extern int permission(struct inode *, int, struct nameidata *);
 extern int generic_permission(struct inode *, int,
 		int (*check_acl)(struct inode *, int));
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1910,7 +1910,7 @@ int __remove_suid(struct path *path, int
 	struct iattr newattrs;
 
 	newattrs.ia_valid = ATTR_FORCE | kill;
-	return notify_change(path->dentry, &newattrs);
+	return notify_change(path->dentry, path->mnt, &newattrs);
 }
 
 int remove_suid(struct path *path)
--- a/mm/tiny-shmem.c
+++ b/mm/tiny-shmem.c
@@ -86,7 +86,7 @@ struct file *shmem_file_setup(char *name
 	file->f_mode = FMODE_WRITE | FMODE_READ;
 
 	/* notify everyone as to the change of file size */
-	error = do_truncate(dentry, size, 0, file);
+	error = do_truncate(dentry, file->f_path.mnt, size, 0, file);
 	if (error < 0)
 		goto close_file;
 

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 04/45] Pass struct vfsmount to the inode_setattr LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (2 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 03/45] Add a vfsmount parameter to notify_change() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 05/45] Add struct vfsmount parameter to vfs_mkdir() jjohansen
                   ` (41 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-setattr.diff --]
[-- Type: text/plain, Size: 3676 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/attr.c                |    4 ++--
 include/linux/security.h |    8 ++++++--
 security/dummy.c         |    3 ++-
 security/selinux/hooks.c |    5 +++--
 4 files changed, 13 insertions(+), 7 deletions(-)

--- a/fs/attr.c
+++ b/fs/attr.c
@@ -144,13 +144,13 @@ int notify_change(struct dentry *dentry,
 		down_write(&dentry->d_inode->i_alloc_sem);
 
 	if (inode->i_op && inode->i_op->setattr) {
-		error = security_inode_setattr(dentry, attr);
+		error = security_inode_setattr(dentry, mnt, attr);
 		if (!error)
 			error = inode->i_op->setattr(dentry, attr);
 	} else {
 		error = inode_change_ok(inode, attr);
 		if (!error)
-			error = security_inode_setattr(dentry, attr);
+			error = security_inode_setattr(dentry, mnt, attr);
 		if (!error) {
 			if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
 			    (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -358,6 +358,7 @@ struct request_sock;
  *	file attributes change (such as when a file is truncated, chown/chmod
  *	operations, transferring disk quotas, etc).
  *	@dentry contains the dentry structure for the file.
+ *	@mnt is the vfsmount corresponding to @dentry (may be NULL).
  *	@attr is the iattr structure containing the new file attributes.
  *	Return 0 if permission is granted.
  * @inode_getattr:
@@ -1221,7 +1222,8 @@ struct security_operations {
 	int (*inode_readlink) (struct dentry *dentry);
 	int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
 	int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
-	int (*inode_setattr)	(struct dentry *dentry, struct iattr *attr);
+	int (*inode_setattr) (struct dentry *dentry, struct vfsmount *mnt,
+			      struct iattr *attr);
 	int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
         void (*inode_delete) (struct inode *inode);
 	int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
@@ -1708,11 +1710,12 @@ static inline int security_inode_permiss
 }
 
 static inline int security_inode_setattr (struct dentry *dentry,
+					  struct vfsmount *mnt,
 					  struct iattr *attr)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_setattr (dentry, attr);
+	return security_ops->inode_setattr (dentry, mnt, attr);
 }
 
 static inline int security_inode_getattr (struct vfsmount *mnt,
@@ -2412,6 +2415,7 @@ static inline int security_inode_permiss
 }
 
 static inline int security_inode_setattr (struct dentry *dentry,
+					  struct vfsmount *mnt,
 					  struct iattr *attr)
 {
 	return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -328,7 +328,8 @@ static int dummy_inode_permission (struc
 	return 0;
 }
 
-static int dummy_inode_setattr (struct dentry *dentry, struct iattr *iattr)
+static int dummy_inode_setattr (struct dentry *dentry, struct vfsmount *mnt,
+				struct iattr *iattr)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2267,11 +2267,12 @@ static int selinux_inode_permission(stru
 			       file_mask_to_av(inode->i_mode, mask), NULL);
 }
 
-static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+static int selinux_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
+				 struct iattr *iattr)
 {
 	int rc;
 
-	rc = secondary_ops->inode_setattr(dentry, iattr);
+	rc = secondary_ops->inode_setattr(dentry, mnt, iattr);
 	if (rc)
 		return rc;
 

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 05/45] Add struct vfsmount parameter to vfs_mkdir()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (3 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 04/45] Pass struct vfsmount to the inode_setattr LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 06/45] Pass struct vfsmount to the inode_mkdir LSM hook jjohansen
                   ` (40 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-mkdir.diff --]
[-- Type: text/plain, Size: 4100 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/ecryptfs/inode.c   |    5 ++++-
 fs/namei.c            |    5 +++--
 fs/nfsd/nfs4recover.c |    3 ++-
 fs/nfsd/vfs.c         |    8 +++++---
 include/linux/fs.h    |    2 +-
 5 files changed, 15 insertions(+), 8 deletions(-)

--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -509,11 +509,14 @@ static int ecryptfs_mkdir(struct inode *
 {
 	int rc;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct dentry *lower_dir_dentry;
 
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
+	lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
 	lower_dir_dentry = lock_parent(lower_dentry);
-	rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode);
+	rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
+		       mode);
 	if (rc || !lower_dentry->d_inode)
 		goto out;
 	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1934,7 +1934,8 @@ asmlinkage long sys_mknod(const char __u
 	return sys_mknodat(AT_FDCWD, filename, mode, dev);
 }
 
-int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+int vfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
+	      int mode)
 {
 	int error = may_create(dir, dentry, NULL);
 
@@ -1978,7 +1979,7 @@ asmlinkage long sys_mkdirat(int dfd, con
 
 	if (!IS_POSIXACL(nd.dentry->d_inode))
 		mode &= ~current->fs->umask;
-	error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
+	error = vfs_mkdir(nd.dentry->d_inode, dentry, nd.mnt, mode);
 	dput(dentry);
 out_unlock:
 	mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -156,7 +156,8 @@ nfsd4_create_clid_dir(struct nfs4_client
 		dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
 		goto out_put;
 	}
-	status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
+	status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, rec_dir.mnt,
+			   S_IRWXU);
 out_put:
 	dput(dentry);
 out_unlock:
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1115,6 +1115,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
 		int type, dev_t rdev, struct svc_fh *resfhp)
 {
 	struct dentry	*dentry, *dchild = NULL;
+	struct svc_export *exp;
 	struct inode	*dirp;
 	__be32		err;
 	int		host_err;
@@ -1131,6 +1132,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
 		goto out;
 
 	dentry = fhp->fh_dentry;
+	exp = fhp->fh_export;
 	dirp = dentry->d_inode;
 
 	err = nfserr_notdir;
@@ -1147,7 +1149,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
 		host_err = PTR_ERR(dchild);
 		if (IS_ERR(dchild))
 			goto out_nfserr;
-		err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
+		err = fh_compose(resfhp, exp, dchild, fhp);
 		if (err)
 			goto out;
 	} else {
@@ -1186,7 +1188,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
 		host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
 		break;
 	case S_IFDIR:
-		host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
+		host_err = vfs_mkdir(dirp, dchild, exp->ex_mnt, iap->ia_mode);
 		break;
 	case S_IFCHR:
 	case S_IFBLK:
@@ -1201,7 +1203,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
 	if (host_err < 0)
 		goto out_nfserr;
 
-	if (EX_ISSYNC(fhp->fh_export)) {
+	if (EX_ISSYNC(exp)) {
 		err = nfserrno(nfsd_sync_dir(dentry));
 		write_inode_now(dchild->d_inode, 1);
 	}
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -992,7 +992,7 @@ extern void unlock_super(struct super_bl
  */
 extern int vfs_permission(struct nameidata *, int);
 extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
-extern int vfs_mkdir(struct inode *, struct dentry *, int);
+extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
 extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
 extern int vfs_symlink(struct inode *, struct dentry *, const char *, int);
 extern int vfs_link(struct dentry *, struct inode *, struct dentry *);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 06/45] Pass struct vfsmount to the inode_mkdir LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (4 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 05/45] Add struct vfsmount parameter to vfs_mkdir() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 07/45] Add a struct vfsmount parameter to vfs_mknod() jjohansen
                   ` (39 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-mkdir.diff --]
[-- Type: text/plain, Size: 3092 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/namei.c               |    2 +-
 include/linux/security.h |    8 ++++++--
 security/dummy.c         |    2 +-
 security/selinux/hooks.c |    3 ++-
 4 files changed, 10 insertions(+), 5 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1946,7 +1946,7 @@ int vfs_mkdir(struct inode *dir, struct 
 		return -EPERM;
 
 	mode &= (S_IRWXUGO|S_ISVTX);
-	error = security_inode_mkdir(dir, dentry, mode);
+	error = security_inode_mkdir(dir, dentry, mnt, mode);
 	if (error)
 		return error;
 
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -308,6 +308,7 @@ struct request_sock;
  *	associated with inode strcture @dir. 
  *	@dir containst the inode structure of parent of the directory to be created.
  *	@dentry contains the dentry structure of new directory.
+ *	@mnt is the vfsmount corresponding to @dentry (may be NULL).
  *	@mode contains the mode of new directory.
  *	Return 0 if permission is granted.
  * @inode_rmdir:
@@ -1213,7 +1214,8 @@ struct security_operations {
 	int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
 	int (*inode_symlink) (struct inode *dir,
 	                      struct dentry *dentry, const char *old_name);
-	int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode);
+	int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
+			    struct vfsmount *mnt, int mode);
 	int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
 	int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
 	                    int mode, dev_t dev);
@@ -1650,11 +1652,12 @@ static inline int security_inode_symlink
 
 static inline int security_inode_mkdir (struct inode *dir,
 					struct dentry *dentry,
+					struct vfsmount *mnt,
 					int mode)
 {
 	if (unlikely (IS_PRIVATE (dir)))
 		return 0;
-	return security_ops->inode_mkdir (dir, dentry, mode);
+	return security_ops->inode_mkdir (dir, dentry, mnt, mode);
 }
 
 static inline int security_inode_rmdir (struct inode *dir,
@@ -2371,6 +2374,7 @@ static inline int security_inode_symlink
 
 static inline int security_inode_mkdir (struct inode *dir,
 					struct dentry *dentry,
+					struct vfsmount *mnt,
 					int mode)
 {
 	return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -288,7 +288,7 @@ static int dummy_inode_symlink (struct i
 }
 
 static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry,
-			      int mask)
+			      struct vfsmount *mnt, int mask)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2207,7 +2207,8 @@ static int selinux_inode_symlink(struct 
 	return may_create(dir, dentry, SECCLASS_LNK_FILE);
 }
 
-static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
+static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry,
+			       struct vfsmount *mnt, int mask)
 {
 	return may_create(dir, dentry, SECCLASS_DIR);
 }

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 07/45] Add a struct vfsmount parameter to vfs_mknod()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (5 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 06/45] Pass struct vfsmount to the inode_mkdir LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 08/45] Pass struct vfsmount to the inode_mknod LSM hook jjohansen
                   ` (38 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-mknod.diff --]
[-- Type: text/plain, Size: 3485 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/ecryptfs/inode.c |    5 ++++-
 fs/namei.c          |   10 ++++++----
 fs/nfsd/vfs.c       |    3 ++-
 include/linux/fs.h  |    2 +-
 net/unix/af_unix.c  |    2 +-
 5 files changed, 14 insertions(+), 8 deletions(-)

--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -560,11 +560,14 @@ ecryptfs_mknod(struct inode *dir, struct
 {
 	int rc;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct dentry *lower_dir_dentry;
 
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
+	lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
 	lower_dir_dentry = lock_parent(lower_dentry);
-	rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev);
+	rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, mode,
+		       dev);
 	if (rc || !lower_dentry->d_inode)
 		goto out;
 	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1855,7 +1855,8 @@ fail:
 }
 EXPORT_SYMBOL_GPL(lookup_create);
 
-int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+int vfs_mknod(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
+	      int mode, dev_t dev)
 {
 	int error = may_create(dir, dentry, NULL);
 
@@ -1907,11 +1908,12 @@ asmlinkage long sys_mknodat(int dfd, con
 			error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
 			break;
 		case S_IFCHR: case S_IFBLK:
-			error = vfs_mknod(nd.dentry->d_inode,dentry,mode,
-					new_decode_dev(dev));
+			error = vfs_mknod(nd.dentry->d_inode, dentry, nd.mnt,
+					  mode, new_decode_dev(dev));
 			break;
 		case S_IFIFO: case S_IFSOCK:
-			error = vfs_mknod(nd.dentry->d_inode,dentry,mode,0);
+			error = vfs_mknod(nd.dentry->d_inode, dentry, nd.mnt,
+					  mode, 0);
 			break;
 		case S_IFDIR:
 			error = -EPERM;
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1194,7 +1194,8 @@ nfsd_create(struct svc_rqst *rqstp, stru
 	case S_IFBLK:
 	case S_IFIFO:
 	case S_IFSOCK:
-		host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
+		host_err = vfs_mknod(dirp, dchild, exp->ex_mnt, iap->ia_mode,
+				     rdev);
 		break;
 	default:
 	        printk("nfsd: bad file type %o in nfsd_create\n", type);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -993,7 +993,7 @@ extern void unlock_super(struct super_bl
 extern int vfs_permission(struct nameidata *, int);
 extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
 extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
-extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
+extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
 extern int vfs_symlink(struct inode *, struct dentry *, const char *, int);
 extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
 extern int vfs_rmdir(struct inode *, struct dentry *);
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -807,7 +807,7 @@ static int unix_bind(struct socket *sock
 		 */
 		mode = S_IFSOCK |
 		       (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
-		err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0);
+		err = vfs_mknod(nd.dentry->d_inode, dentry, nd.mnt, mode, 0);
 		if (err)
 			goto out_mknod_dput;
 		mutex_unlock(&nd.dentry->d_inode->i_mutex);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 08/45] Pass struct vfsmount to the inode_mknod LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (6 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 07/45] Add a struct vfsmount parameter to vfs_mknod() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 09/45] Add a struct vfsmount parameter to vfs_symlink() jjohansen
                   ` (37 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-mknod.diff --]
[-- Type: text/plain, Size: 3206 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/namei.c               |    2 +-
 include/linux/security.h |    7 +++++--
 security/dummy.c         |    2 +-
 security/selinux/hooks.c |    5 +++--
 4 files changed, 10 insertions(+), 6 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1869,7 +1869,7 @@ int vfs_mknod(struct inode *dir, struct 
 	if (!dir->i_op || !dir->i_op->mknod)
 		return -EPERM;
 
-	error = security_inode_mknod(dir, dentry, mode, dev);
+	error = security_inode_mknod(dir, dentry, mnt, mode, dev);
 	if (error)
 		return error;
 
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -323,6 +323,7 @@ struct request_sock;
  *	and not this hook.
  *	@dir contains the inode structure of parent of the new file.
  *	@dentry contains the dentry structure of the new file.
+ *	@mnt is the vfsmount corresponding to @dentry (may be NULL).
  *	@mode contains the mode of the new file.
  *	@dev contains the device number.
  *	Return 0 if permission is granted.
@@ -1218,7 +1219,7 @@ struct security_operations {
 			    struct vfsmount *mnt, int mode);
 	int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
 	int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
-	                    int mode, dev_t dev);
+			    struct vfsmount *mnt, int mode, dev_t dev);
 	int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
 	                     struct inode *new_dir, struct dentry *new_dentry);
 	int (*inode_readlink) (struct dentry *dentry);
@@ -1670,11 +1671,12 @@ static inline int security_inode_rmdir (
 
 static inline int security_inode_mknod (struct inode *dir,
 					struct dentry *dentry,
+					struct vfsmount *mnt,
 					int mode, dev_t dev)
 {
 	if (unlikely (IS_PRIVATE (dir)))
 		return 0;
-	return security_ops->inode_mknod (dir, dentry, mode, dev);
+	return security_ops->inode_mknod (dir, dentry, mnt, mode, dev);
 }
 
 static inline int security_inode_rename (struct inode *old_dir,
@@ -2388,6 +2390,7 @@ static inline int security_inode_rmdir (
 
 static inline int security_inode_mknod (struct inode *dir,
 					struct dentry *dentry,
+					struct vfsmount *mnt,
 					int mode, dev_t dev)
 {
 	return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -299,7 +299,7 @@ static int dummy_inode_rmdir (struct ino
 }
 
 static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry,
-			      int mode, dev_t dev)
+			      struct vfsmount *mnt, int mode, dev_t dev)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2218,11 +2218,12 @@ static int selinux_inode_rmdir(struct in
 	return may_link(dir, dentry, MAY_RMDIR);
 }
 
-static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry,
+			       struct vfsmount *mnt, int mode, dev_t dev)
 {
 	int rc;
 
-	rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
+	rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev);
 	if (rc)
 		return rc;
 

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 09/45] Add a struct vfsmount parameter to vfs_symlink()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (7 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 08/45] Pass struct vfsmount to the inode_mknod LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 10/45] Pass struct vfsmount to the inode_symlink LSM hook jjohansen
                   ` (36 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-symlink.diff --]
[-- Type: text/plain, Size: 4135 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/ecryptfs/inode.c |    4 +++-
 fs/namei.c          |    6 ++++--
 fs/nfsd/vfs.c       |   12 ++++++++----
 include/linux/fs.h  |    2 +-
 4 files changed, 16 insertions(+), 8 deletions(-)

--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -470,6 +470,7 @@ static int ecryptfs_symlink(struct inode
 {
 	int rc;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct dentry *lower_dir_dentry;
 	umode_t mode;
 	char *encoded_symname;
@@ -478,6 +479,7 @@ static int ecryptfs_symlink(struct inode
 
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
 	dget(lower_dentry);
+	lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
 	lower_dir_dentry = lock_parent(lower_dentry);
 	mode = S_IALLUGO;
 	encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
@@ -487,7 +489,7 @@ static int ecryptfs_symlink(struct inode
 		rc = encoded_symlen;
 		goto out_lock;
 	}
-	rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
+	rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
 			 encoded_symname, mode);
 	kfree(encoded_symname);
 	if (rc || !lower_dentry->d_inode)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2203,7 +2203,8 @@ asmlinkage long sys_unlink(const char __
 	return do_unlinkat(AT_FDCWD, pathname);
 }
 
-int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
+int vfs_symlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
+		const char *oldname, int mode)
 {
 	int error = may_create(dir, dentry, NULL);
 
@@ -2249,7 +2250,8 @@ asmlinkage long sys_symlinkat(const char
 	if (IS_ERR(dentry))
 		goto out_unlock;
 
-	error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
+	error = vfs_symlink(nd.dentry->d_inode, dentry, nd.mnt, from,
+			    S_IALLUGO);
 	dput(dentry);
 out_unlock:
 	mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1436,6 +1436,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
 				struct iattr *iap)
 {
 	struct dentry	*dentry, *dnew;
+	struct svc_export *exp;
 	__be32		err, cerr;
 	int		host_err;
 	umode_t		mode;
@@ -1462,6 +1463,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
 	if (iap && (iap->ia_valid & ATTR_MODE))
 		mode = iap->ia_mode & S_IALLUGO;
 
+	exp = fhp->fh_export;
 	if (unlikely(path[plen] != 0)) {
 		char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
 		if (path_alloced == NULL)
@@ -1469,20 +1471,22 @@ nfsd_symlink(struct svc_rqst *rqstp, str
 		else {
 			strncpy(path_alloced, path, plen);
 			path_alloced[plen] = 0;
-			host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode);
+			host_err = vfs_symlink(dentry->d_inode, dnew,
+					       exp->ex_mnt, path_alloced, mode);
 			kfree(path_alloced);
 		}
 	} else
-		host_err = vfs_symlink(dentry->d_inode, dnew, path, mode);
+		host_err = vfs_symlink(dentry->d_inode, dnew, exp->ex_mnt, path,
+				       mode);
 
 	if (!host_err) {
-		if (EX_ISSYNC(fhp->fh_export))
+		if (EX_ISSYNC(exp))
 			host_err = nfsd_sync_dir(dentry);
 	}
 	err = nfserrno(host_err);
 	fh_unlock(fhp);
 
-	cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
+	cerr = fh_compose(resfhp, exp, dnew, fhp);
 	dput(dnew);
 	if (err==0) err = cerr;
 out:
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -994,7 +994,7 @@ extern int vfs_permission(struct nameida
 extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
 extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
 extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
-extern int vfs_symlink(struct inode *, struct dentry *, const char *, int);
+extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int);
 extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
 extern int vfs_rmdir(struct inode *, struct dentry *);
 extern int vfs_unlink(struct inode *, struct dentry *);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 10/45] Pass struct vfsmount to the inode_symlink LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (8 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 09/45] Add a struct vfsmount parameter to vfs_symlink() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 11/45] Pass struct vfsmount to the inode_readlink " jjohansen
                   ` (35 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-symlink.diff --]
[-- Type: text/plain, Size: 3260 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/namei.c               |    2 +-
 include/linux/security.h |    9 ++++++---
 security/dummy.c         |    2 +-
 security/selinux/hooks.c |    3 ++-
 4 files changed, 10 insertions(+), 6 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2214,7 +2214,7 @@ int vfs_symlink(struct inode *dir, struc
 	if (!dir->i_op || !dir->i_op->symlink)
 		return -EPERM;
 
-	error = security_inode_symlink(dir, dentry, oldname);
+	error = security_inode_symlink(dir, dentry, mnt, oldname);
 	if (error)
 		return error;
 
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -301,6 +301,7 @@ struct request_sock;
  *	Check the permission to create a symbolic link to a file.
  *	@dir contains the inode structure of parent directory of the symbolic link.
  *	@dentry contains the dentry structure of the symbolic link.
+ *	@mnt is the vfsmount corresponding to @dentry (may be NULL).
  *	@old_name contains the pathname of file.
  *	Return 0 if permission is granted.
  * @inode_mkdir:
@@ -1213,8 +1214,8 @@ struct security_operations {
 	int (*inode_link) (struct dentry *old_dentry,
 	                   struct inode *dir, struct dentry *new_dentry);
 	int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
-	int (*inode_symlink) (struct inode *dir,
-	                      struct dentry *dentry, const char *old_name);
+	int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
+			      struct vfsmount *mnt, const char *old_name);
 	int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
 			    struct vfsmount *mnt, int mode);
 	int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
@@ -1644,11 +1645,12 @@ static inline int security_inode_unlink 
 
 static inline int security_inode_symlink (struct inode *dir,
 					  struct dentry *dentry,
+					  struct vfsmount *mnt,
 					  const char *old_name)
 {
 	if (unlikely (IS_PRIVATE (dir)))
 		return 0;
-	return security_ops->inode_symlink (dir, dentry, old_name);
+	return security_ops->inode_symlink (dir, dentry, mnt, old_name);
 }
 
 static inline int security_inode_mkdir (struct inode *dir,
@@ -2369,6 +2371,7 @@ static inline int security_inode_unlink 
 
 static inline int security_inode_symlink (struct inode *dir,
 					  struct dentry *dentry,
+					  struct vfsmount *mnt,
 					  const char *old_name)
 {
 	return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -282,7 +282,7 @@ static int dummy_inode_unlink (struct in
 }
 
 static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry,
-				const char *name)
+				struct vfsmount *mnt, const char *name)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2202,7 +2202,8 @@ static int selinux_inode_unlink(struct i
 	return may_link(dir, dentry, MAY_UNLINK);
 }
 
-static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
+static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry,
+				 struct vfsmount *mnt, const char *name)
 {
 	return may_create(dir, dentry, SECCLASS_LNK_FILE);
 }

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 11/45] Pass struct vfsmount to the inode_readlink LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (9 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 10/45] Pass struct vfsmount to the inode_symlink LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 12/45] Add struct vfsmount parameters to vfs_link() jjohansen
                   ` (34 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-readlink.diff --]
[-- Type: text/plain, Size: 3282 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/stat.c                |    2 +-
 include/linux/security.h |   11 +++++++----
 security/dummy.c         |    2 +-
 security/selinux/hooks.c |    2 +-
 4 files changed, 10 insertions(+), 7 deletions(-)

--- a/fs/stat.c
+++ b/fs/stat.c
@@ -306,7 +306,7 @@ asmlinkage long sys_readlinkat(int dfd, 
 
 		error = -EINVAL;
 		if (inode->i_op && inode->i_op->readlink) {
-			error = security_inode_readlink(nd.dentry);
+			error = security_inode_readlink(nd.dentry, nd.mnt);
 			if (!error) {
 				touch_atime(nd.mnt, nd.dentry);
 				error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -338,6 +338,7 @@ struct request_sock;
  * @inode_readlink:
  *	Check the permission to read the symbolic link.
  *	@dentry contains the dentry structure for the file link.
+ *	@mnt is the vfsmount corresponding to @dentry (may be NULL).
  *	Return 0 if permission is granted.
  * @inode_follow_link:
  *	Check permission to follow a symbolic link when looking up a pathname.
@@ -1223,7 +1224,7 @@ struct security_operations {
 			    struct vfsmount *mnt, int mode, dev_t dev);
 	int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
 	                     struct inode *new_dir, struct dentry *new_dentry);
-	int (*inode_readlink) (struct dentry *dentry);
+	int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt);
 	int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
 	int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
 	int (*inode_setattr) (struct dentry *dentry, struct vfsmount *mnt,
@@ -1693,11 +1694,12 @@ static inline int security_inode_rename 
 					   new_dir, new_dentry);
 }
 
-static inline int security_inode_readlink (struct dentry *dentry)
+static inline int security_inode_readlink (struct dentry *dentry,
+					   struct vfsmount *mnt)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_readlink (dentry);
+	return security_ops->inode_readlink (dentry, mnt);
 }
 
 static inline int security_inode_follow_link (struct dentry *dentry,
@@ -2407,7 +2409,8 @@ static inline int security_inode_rename 
 	return 0;
 }
 
-static inline int security_inode_readlink (struct dentry *dentry)
+static inline int security_inode_readlink (struct dentry *dentry,
+					   struct vfsmount *mnt)
 {
 	return 0;
 }
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -312,7 +312,7 @@ static int dummy_inode_rename (struct in
 	return 0;
 }
 
-static int dummy_inode_readlink (struct dentry *dentry)
+static int dummy_inode_readlink (struct dentry *dentry, struct vfsmount *mnt)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2237,7 +2237,7 @@ static int selinux_inode_rename(struct i
 	return may_rename(old_inode, old_dentry, new_inode, new_dentry);
 }
 
-static int selinux_inode_readlink(struct dentry *dentry)
+static int selinux_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
 {
 	return dentry_has_perm(current, NULL, dentry, FILE__READ);
 }

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 12/45] Add struct vfsmount parameters to vfs_link()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (10 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 11/45] Pass struct vfsmount to the inode_readlink " jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 13/45] Pass the struct vfsmounts to the inode_link LSM hook jjohansen
                   ` (33 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-link.diff --]
[-- Type: text/plain, Size: 3494 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/ecryptfs/inode.c |    9 +++++++--
 fs/namei.c          |    5 +++--
 fs/nfsd/vfs.c       |    3 ++-
 include/linux/fs.h  |    2 +-
 4 files changed, 13 insertions(+), 6 deletions(-)

--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -411,19 +411,24 @@ static int ecryptfs_link(struct dentry *
 			 struct dentry *new_dentry)
 {
 	struct dentry *lower_old_dentry;
+	struct vfsmount *lower_old_mnt;
 	struct dentry *lower_new_dentry;
+	struct vfsmount *lower_new_mnt;
 	struct dentry *lower_dir_dentry;
 	u64 file_size_save;
 	int rc;
 
 	file_size_save = i_size_read(old_dentry->d_inode);
 	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
+	lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
 	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
+	lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
 	dget(lower_old_dentry);
 	dget(lower_new_dentry);
 	lower_dir_dentry = lock_parent(lower_new_dentry);
-	rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
-		      lower_new_dentry);
+	rc = vfs_link(lower_old_dentry, lower_old_mnt,
+		      lower_dir_dentry->d_inode, lower_new_dentry,
+		      lower_new_mnt);
 	if (rc || !lower_new_dentry->d_inode)
 		goto out_lock;
 	rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2268,7 +2268,7 @@ asmlinkage long sys_symlink(const char _
 	return sys_symlinkat(oldname, AT_FDCWD, newname);
 }
 
-int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
+int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir, struct dentry *new_dentry, struct vfsmount *new_mnt)
 {
 	struct inode *inode = old_dentry->d_inode;
 	int error;
@@ -2346,7 +2346,8 @@ asmlinkage long sys_linkat(int olddfd, c
 	error = PTR_ERR(new_dentry);
 	if (IS_ERR(new_dentry))
 		goto out_unlock;
-	error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
+	error = vfs_link(old_nd.dentry, old_nd.mnt, nd.dentry->d_inode,
+			 new_dentry, nd.mnt);
 	dput(new_dentry);
 out_unlock:
 	mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1536,7 +1536,8 @@ nfsd_link(struct svc_rqst *rqstp, struct
 	dold = tfhp->fh_dentry;
 	dest = dold->d_inode;
 
-	host_err = vfs_link(dold, dirp, dnew);
+	host_err = vfs_link(dold, tfhp->fh_export->ex_mnt, dirp,
+			    dnew, ffhp->fh_export->ex_mnt);
 	if (!host_err) {
 		if (EX_ISSYNC(ffhp->fh_export)) {
 			err = nfserrno(nfsd_sync_dir(ddir));
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -995,7 +995,7 @@ extern int vfs_create(struct inode *, st
 extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
 extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
 extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int);
-extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
+extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
 extern int vfs_rmdir(struct inode *, struct dentry *);
 extern int vfs_unlink(struct inode *, struct dentry *);
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 13/45] Pass the struct vfsmounts to the inode_link LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (11 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 12/45] Add struct vfsmount parameters to vfs_link() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 14/45] Add a struct vfsmount parameter to vfs_rmdir() jjohansen
                   ` (32 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-link.diff --]
[-- Type: text/plain, Size: 4246 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/namei.c               |    3 ++-
 include/linux/security.h |   18 +++++++++++++-----
 security/dummy.c         |    6 ++++--
 security/selinux/hooks.c |    9 +++++++--
 4 files changed, 26 insertions(+), 10 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2293,7 +2293,8 @@ int vfs_link(struct dentry *old_dentry, 
 	if (S_ISDIR(old_dentry->d_inode->i_mode))
 		return -EPERM;
 
-	error = security_inode_link(old_dentry, dir, new_dentry);
+	error = security_inode_link(old_dentry, old_mnt, dir, new_dentry,
+				    new_mnt);
 	if (error)
 		return error;
 
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -289,8 +289,10 @@ struct request_sock;
  * @inode_link:
  *	Check permission before creating a new hard link to a file.
  *	@old_dentry contains the dentry structure for an existing link to the file.
+ *	@old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
  *	@dir contains the inode structure of the parent directory of the new link.
  *	@new_dentry contains the dentry structure for the new link.
+ *	@new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
  *	Return 0 if permission is granted.
  * @inode_unlink:
  *	Check the permission to remove a hard link to a file. 
@@ -1212,8 +1214,9 @@ struct security_operations {
 				    char **name, void **value, size_t *len);
 	int (*inode_create) (struct inode *dir, struct dentry *dentry,
 			     struct vfsmount *mnt, int mode);
-	int (*inode_link) (struct dentry *old_dentry,
-	                   struct inode *dir, struct dentry *new_dentry);
+	int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt,
+	                   struct inode *dir, struct dentry *new_dentry,
+			   struct vfsmount *new_mnt);
 	int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
 	int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
 			      struct vfsmount *mnt, const char *old_name);
@@ -1628,12 +1631,15 @@ static inline int security_inode_create 
 }
 
 static inline int security_inode_link (struct dentry *old_dentry,
+				       struct vfsmount *old_mnt,
 				       struct inode *dir,
-				       struct dentry *new_dentry)
+				       struct dentry *new_dentry,
+				       struct vfsmount *new_mnt)
 {
 	if (unlikely (IS_PRIVATE (old_dentry->d_inode)))
 		return 0;
-	return security_ops->inode_link (old_dentry, dir, new_dentry);
+	return security_ops->inode_link (old_dentry, old_mnt, dir,
+					 new_dentry, new_mnt);
 }
 
 static inline int security_inode_unlink (struct inode *dir,
@@ -2359,8 +2365,10 @@ static inline int security_inode_create 
 }
 
 static inline int security_inode_link (struct dentry *old_dentry,
+				       struct vfsmount *old_mnt,
 				       struct inode *dir,
-				       struct dentry *new_dentry)
+				       struct dentry *new_dentry,
+				       struct vfsmount *new_mnt)
 {
 	return 0;
 }
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -270,8 +270,10 @@ static int dummy_inode_create (struct in
 	return 0;
 }
 
-static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode,
-			     struct dentry *new_dentry)
+static int dummy_inode_link (struct dentry *old_dentry,
+			     struct vfsmount *old_mnt, struct inode *inode,
+			     struct dentry *new_dentry,
+			     struct vfsmount *new_mnt)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2182,11 +2182,16 @@ static int selinux_inode_create(struct i
 	return may_create(dir, dentry, SECCLASS_FILE);
 }
 
-static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
+static int selinux_inode_link(struct dentry *old_dentry,
+			      struct vfsmount *old_mnt,
+			      struct inode *dir,
+			      struct dentry *new_dentry,
+			      struct vfsmount *new_mnt)
 {
 	int rc;
 
-	rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
+	rc = secondary_ops->inode_link(old_dentry, old_mnt, dir, new_dentry,
+				       new_mnt);
 	if (rc)
 		return rc;
 	return may_link(dir, old_dentry, MAY_LINK);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 14/45] Add a struct vfsmount parameter to vfs_rmdir()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (12 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 13/45] Pass the struct vfsmounts to the inode_link LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 15/45] Pass struct vfsmount to the inode_rmdir LSM hook jjohansen
                   ` (31 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-rmdir.diff --]
[-- Type: text/plain, Size: 4410 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/ecryptfs/inode.c   |    4 +++-
 fs/namei.c            |    4 ++--
 fs/nfsd/nfs4recover.c |    2 +-
 fs/nfsd/vfs.c         |    8 +++++---
 fs/reiserfs/xattr.c   |    2 +-
 include/linux/fs.h    |    2 +-
 6 files changed, 13 insertions(+), 9 deletions(-)

--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -542,14 +542,16 @@ out:
 static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct dentry *lower_dir_dentry;
 	int rc;
 
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
+	lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
 	dget(dentry);
 	lower_dir_dentry = lock_parent(lower_dentry);
 	dget(lower_dentry);
-	rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
+	rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt);
 	dput(lower_dentry);
 	if (!rc)
 		d_delete(lower_dentry);
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2024,7 +2024,7 @@ void dentry_unhash(struct dentry *dentry
 	spin_unlock(&dcache_lock);
 }
 
-int vfs_rmdir(struct inode *dir, struct dentry *dentry)
+int vfs_rmdir(struct inode *dir, struct dentry *dentry,struct vfsmount *mnt)
 {
 	int error = may_delete(dir, dentry, 1);
 
@@ -2088,7 +2088,7 @@ static long do_rmdir(int dfd, const char
 	error = PTR_ERR(dentry);
 	if (IS_ERR(dentry))
 		goto exit2;
-	error = vfs_rmdir(nd.dentry->d_inode, dentry);
+	error = vfs_rmdir(nd.dentry->d_inode, dentry, nd.mnt);
 	dput(dentry);
 exit2:
 	mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -276,7 +276,7 @@ nfsd4_clear_clid_dir(struct dentry *dir,
 	 * a kernel from the future.... */
 	nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
 	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
-	status = vfs_rmdir(dir->d_inode, dentry);
+	status = vfs_rmdir(dir->d_inode, dentry, rec_dir.mnt);
 	mutex_unlock(&dir->d_inode->i_mutex);
 	return status;
 }
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1666,6 +1666,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
 				char *fname, int flen)
 {
 	struct dentry	*dentry, *rdentry;
+	struct svc_export *exp;
 	struct inode	*dirp;
 	__be32		err;
 	int		host_err;
@@ -1680,6 +1681,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
 	fh_lock_nested(fhp, I_MUTEX_PARENT);
 	dentry = fhp->fh_dentry;
 	dirp = dentry->d_inode;
+	exp = fhp->fh_export;
 
 	rdentry = lookup_one_len(fname, dentry, flen);
 	host_err = PTR_ERR(rdentry);
@@ -1697,21 +1699,21 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
 
 	if (type != S_IFDIR) { /* It's UNLINK */
 #ifdef MSNFS
-		if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
+		if ((exp->ex_flags & NFSEXP_MSNFS) &&
 			(atomic_read(&rdentry->d_count) > 1)) {
 			host_err = -EPERM;
 		} else
 #endif
 		host_err = vfs_unlink(dirp, rdentry);
 	} else { /* It's RMDIR */
-		host_err = vfs_rmdir(dirp, rdentry);
+		host_err = vfs_rmdir(dirp, rdentry, exp->ex_mnt);
 	}
 
 	dput(rdentry);
 
 	if (host_err)
 		goto out_nfserr;
-	if (EX_ISSYNC(fhp->fh_export))
+	if (EX_ISSYNC(exp))
 		host_err = nfsd_sync_dir(dentry);
 
 out_nfserr:
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -775,7 +775,7 @@ int reiserfs_delete_xattrs(struct inode 
 	if (dir->d_inode->i_nlink <= 2) {
 		root = get_xa_root(inode->i_sb, XATTR_REPLACE);
 		reiserfs_write_lock_xattrs(inode->i_sb);
-		err = vfs_rmdir(root->d_inode, dir);
+		err = vfs_rmdir(root->d_inode, dir, NULL);
 		reiserfs_write_unlock_xattrs(inode->i_sb);
 		dput(root);
 	} else {
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -996,7 +996,7 @@ extern int vfs_mkdir(struct inode *, str
 extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
 extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int);
 extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
-extern int vfs_rmdir(struct inode *, struct dentry *);
+extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
 extern int vfs_unlink(struct inode *, struct dentry *);
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 15/45] Pass struct vfsmount to the inode_rmdir LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (13 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 14/45] Add a struct vfsmount parameter to vfs_rmdir() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 16/45] Call lsm hook before unhashing dentry in vfs_rmdir() jjohansen
                   ` (30 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-rmdir.diff --]
[-- Type: text/plain, Size: 3218 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/namei.c               |    2 +-
 include/linux/security.h |   12 ++++++++----
 security/dummy.c         |    3 ++-
 security/selinux/hooks.c |    3 ++-
 4 files changed, 13 insertions(+), 7 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2041,7 +2041,7 @@ int vfs_rmdir(struct inode *dir, struct 
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
-		error = security_inode_rmdir(dir, dentry);
+		error = security_inode_rmdir(dir, dentry, mnt);
 		if (!error) {
 			error = dir->i_op->rmdir(dir, dentry);
 			if (!error)
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -318,6 +318,7 @@ struct request_sock;
  *	Check the permission to remove a directory.
  *	@dir contains the inode structure of parent of the directory to be removed.
  *	@dentry contains the dentry structure of directory to be removed.
+ *	@mnt is the vfsmount corresponding to @dentry (may be NULL).
  *	Return 0 if permission is granted.
  * @inode_mknod:
  *	Check permissions when creating a special file (or a socket or a fifo
@@ -1222,7 +1223,8 @@ struct security_operations {
 			      struct vfsmount *mnt, const char *old_name);
 	int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
 			    struct vfsmount *mnt, int mode);
-	int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
+	int (*inode_rmdir) (struct inode *dir, struct dentry *dentry,
+			    struct vfsmount *mnt);
 	int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
 			    struct vfsmount *mnt, int mode, dev_t dev);
 	int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
@@ -1671,11 +1673,12 @@ static inline int security_inode_mkdir (
 }
 
 static inline int security_inode_rmdir (struct inode *dir,
-					struct dentry *dentry)
+					struct dentry *dentry,
+					struct vfsmount *mnt)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_rmdir (dir, dentry);
+	return security_ops->inode_rmdir (dir, dentry, mnt);
 }
 
 static inline int security_inode_mknod (struct inode *dir,
@@ -2396,7 +2399,8 @@ static inline int security_inode_mkdir (
 }
 
 static inline int security_inode_rmdir (struct inode *dir,
-					struct dentry *dentry)
+					struct dentry *dentry,
+					struct vfsmount *mnt)
 {
 	return 0;
 }
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -295,7 +295,8 @@ static int dummy_inode_mkdir (struct ino
 	return 0;
 }
 
-static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry)
+static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry,
+			      struct vfsmount *mnt)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2219,7 +2219,8 @@ static int selinux_inode_mkdir(struct in
 	return may_create(dir, dentry, SECCLASS_DIR);
 }
 
-static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
+static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry,
+			       struct vfsmount *mnt)
 {
 	return may_link(dir, dentry, MAY_RMDIR);
 }

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 16/45] Call lsm hook before unhashing dentry in vfs_rmdir()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (14 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 15/45] Pass struct vfsmount to the inode_rmdir LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 17/45] Add a struct vfsmount parameter to vfs_unlink() jjohansen
                   ` (29 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, John Johansen, Andreas Gruenbacher

[-- Attachment #1: fix-vfs_rmdir.diff --]
[-- Type: text/plain, Size: 1172 bytes --]

If we unhash the dentry before calling the security_inode_rmdir hook,
we cannot compute the file's pathname in the hook anymore. AppArmor
needs to know the filename in order to decide whether a file may be
deleted, though.

Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 fs/namei.c |   13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2034,6 +2034,10 @@ int vfs_rmdir(struct inode *dir, struct 
 	if (!dir->i_op || !dir->i_op->rmdir)
 		return -EPERM;
 
+	error = security_inode_rmdir(dir, dentry, mnt);
+	if (error)
+		return error;
+
 	DQUOT_INIT(dir);
 
 	mutex_lock(&dentry->d_inode->i_mutex);
@@ -2041,12 +2045,9 @@ int vfs_rmdir(struct inode *dir, struct 
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
-		error = security_inode_rmdir(dir, dentry, mnt);
-		if (!error) {
-			error = dir->i_op->rmdir(dir, dentry);
-			if (!error)
-				dentry->d_inode->i_flags |= S_DEAD;
-		}
+		error = dir->i_op->rmdir(dir, dentry);
+		if (!error)
+			dentry->d_inode->i_flags |= S_DEAD;
 	}
 	mutex_unlock(&dentry->d_inode->i_mutex);
 	if (!error) {

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 17/45] Add a struct vfsmount parameter to vfs_unlink()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (15 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 16/45] Call lsm hook before unhashing dentry in vfs_rmdir() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 18/45] Pass struct vfsmount to the inode_unlink LSM hook jjohansen
                   ` (28 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-unlink.diff --]
[-- Type: text/plain, Size: 3265 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/ecryptfs/inode.c   |    3 ++-
 fs/namei.c            |    4 ++--
 fs/nfsd/nfs4recover.c |    2 +-
 fs/nfsd/vfs.c         |    2 +-
 include/linux/fs.h    |    2 +-
 ipc/mqueue.c          |    2 +-
 6 files changed, 8 insertions(+), 7 deletions(-)

--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -453,10 +453,11 @@ static int ecryptfs_unlink(struct inode 
 {
 	int rc = 0;
 	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+	struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
 	struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
 
 	lock_parent(lower_dentry);
-	rc = vfs_unlink(lower_dir_inode, lower_dentry);
+	rc = vfs_unlink(lower_dir_inode, lower_dentry, lower_mnt);
 	if (rc) {
 		printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
 		goto out_unlock;
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2105,7 +2105,7 @@ asmlinkage long sys_rmdir(const char __u
 	return do_rmdir(AT_FDCWD, pathname);
 }
 
-int vfs_unlink(struct inode *dir, struct dentry *dentry)
+int vfs_unlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt)
 {
 	int error = may_delete(dir, dentry, 0);
 
@@ -2169,7 +2169,7 @@ static long do_unlinkat(int dfd, const c
 		inode = dentry->d_inode;
 		if (inode)
 			atomic_inc(&inode->i_count);
-		error = vfs_unlink(nd.dentry->d_inode, dentry);
+		error = vfs_unlink(nd.dentry->d_inode, dentry, nd.mnt);
 	exit2:
 		dput(dentry);
 	}
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -261,7 +261,7 @@ nfsd4_remove_clid_file(struct dentry *di
 		return -EINVAL;
 	}
 	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
-	status = vfs_unlink(dir->d_inode, dentry);
+	status = vfs_unlink(dir->d_inode, dentry, rec_dir.mnt);
 	mutex_unlock(&dir->d_inode->i_mutex);
 	return status;
 }
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1704,7 +1704,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
 			host_err = -EPERM;
 		} else
 #endif
-		host_err = vfs_unlink(dirp, rdentry);
+		host_err = vfs_unlink(dirp, rdentry, exp->ex_mnt);
 	} else { /* It's RMDIR */
 		host_err = vfs_rmdir(dirp, rdentry, exp->ex_mnt);
 	}
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -997,7 +997,7 @@ extern int vfs_mknod(struct inode *, str
 extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int);
 extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
 extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
-extern int vfs_unlink(struct inode *, struct dentry *);
+extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 
 /*
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -749,7 +749,7 @@ asmlinkage long sys_mq_unlink(const char
 	if (inode)
 		atomic_inc(&inode->i_count);
 
-	err = vfs_unlink(dentry->d_parent->d_inode, dentry);
+	err = vfs_unlink(dentry->d_parent->d_inode, dentry, mqueue_mnt);
 out_err:
 	dput(dentry);
 

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 18/45] Pass struct vfsmount to the inode_unlink LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (16 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 17/45] Add a struct vfsmount parameter to vfs_unlink() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 19/45] Add struct vfsmount parameters to vfs_rename() jjohansen
                   ` (27 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-unlink.diff --]
[-- Type: text/plain, Size: 3367 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/namei.c               |    2 +-
 include/linux/security.h |   12 ++++++++----
 security/dummy.c         |    3 ++-
 security/selinux/hooks.c |    5 +++--
 4 files changed, 14 insertions(+), 8 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2121,7 +2121,7 @@ int vfs_unlink(struct inode *dir, struct
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
-		error = security_inode_unlink(dir, dentry);
+		error = security_inode_unlink(dir, dentry, mnt);
 		if (!error)
 			error = dir->i_op->unlink(dir, dentry);
 	}
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -298,6 +298,7 @@ struct request_sock;
  *	Check the permission to remove a hard link to a file. 
  *	@dir contains the inode structure of parent directory of the file.
  *	@dentry contains the dentry structure for file to be unlinked.
+ *	@mnt is the vfsmount corresponding to @dentry (may be NULL).
  *	Return 0 if permission is granted.
  * @inode_symlink:
  *	Check the permission to create a symbolic link to a file.
@@ -1218,7 +1219,8 @@ struct security_operations {
 	int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt,
 	                   struct inode *dir, struct dentry *new_dentry,
 			   struct vfsmount *new_mnt);
-	int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
+	int (*inode_unlink) (struct inode *dir, struct dentry *dentry,
+			     struct vfsmount *mnt);
 	int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
 			      struct vfsmount *mnt, const char *old_name);
 	int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
@@ -1645,11 +1647,12 @@ static inline int security_inode_link (s
 }
 
 static inline int security_inode_unlink (struct inode *dir,
-					 struct dentry *dentry)
+					 struct dentry *dentry,
+					 struct vfsmount *mnt)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_unlink (dir, dentry);
+	return security_ops->inode_unlink (dir, dentry, mnt);
 }
 
 static inline int security_inode_symlink (struct inode *dir,
@@ -2377,7 +2380,8 @@ static inline int security_inode_link (s
 }
 
 static inline int security_inode_unlink (struct inode *dir,
-					 struct dentry *dentry)
+					 struct dentry *dentry,
+					 struct vfsmount *mnt)
 {
 	return 0;
 }
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -278,7 +278,8 @@ static int dummy_inode_link (struct dent
 	return 0;
 }
 
-static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry)
+static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry,
+			       struct vfsmount *mnt)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2197,11 +2197,12 @@ static int selinux_inode_link(struct den
 	return may_link(dir, old_dentry, MAY_LINK);
 }
 
-static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
+static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry,
+			        struct vfsmount *mnt)
 {
 	int rc;
 
-	rc = secondary_ops->inode_unlink(dir, dentry);
+	rc = secondary_ops->inode_unlink(dir, dentry, mnt);
 	if (rc)
 		return rc;
 	return may_link(dir, dentry, MAY_UNLINK);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 19/45] Add struct vfsmount parameters to vfs_rename()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (17 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 18/45] Pass struct vfsmount to the inode_unlink LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 20/45] Pass struct vfsmount to the inode_rename LSM hook jjohansen
                   ` (26 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-rename.diff --]
[-- Type: text/plain, Size: 4708 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/ecryptfs/inode.c |    7 ++++++-
 fs/namei.c          |   19 ++++++++++++-------
 fs/nfsd/vfs.c       |    3 ++-
 include/linux/fs.h  |    2 +-
 4 files changed, 21 insertions(+), 10 deletions(-)

--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -598,19 +598,24 @@ ecryptfs_rename(struct inode *old_dir, s
 {
 	int rc;
 	struct dentry *lower_old_dentry;
+	struct vfsmount *lower_old_mnt;
 	struct dentry *lower_new_dentry;
+	struct vfsmount *lower_new_mnt;
 	struct dentry *lower_old_dir_dentry;
 	struct dentry *lower_new_dir_dentry;
 
 	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
+	lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
 	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
+	lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
 	dget(lower_old_dentry);
 	dget(lower_new_dentry);
 	lower_old_dir_dentry = dget_parent(lower_old_dentry);
 	lower_new_dir_dentry = dget_parent(lower_new_dentry);
 	lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
 	rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
-			lower_new_dir_dentry->d_inode, lower_new_dentry);
+			lower_old_mnt, lower_new_dir_dentry->d_inode,
+			lower_new_dentry, lower_new_mnt);
 	if (rc)
 		goto out_lock;
 	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2401,7 +2401,8 @@ asmlinkage long sys_link(const char __us
  *	   locking].
  */
 static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-			  struct inode *new_dir, struct dentry *new_dentry)
+			  struct vfsmount *old_mnt, struct inode *new_dir,
+			  struct dentry *new_dentry, struct vfsmount *new_mnt)
 {
 	int error = 0;
 	struct inode *target;
@@ -2444,7 +2445,8 @@ static int vfs_rename_dir(struct inode *
 }
 
 static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-			    struct inode *new_dir, struct dentry *new_dentry)
+			    struct vfsmount *old_mnt, struct inode *new_dir,
+			    struct dentry *new_dentry, struct vfsmount *new_mnt)
 {
 	struct inode *target;
 	int error;
@@ -2472,7 +2474,8 @@ static int vfs_rename_other(struct inode
 }
 
 int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-	       struct inode *new_dir, struct dentry *new_dentry)
+	        struct vfsmount *old_mnt, struct inode *new_dir,
+	        struct dentry *new_dentry, struct vfsmount *new_mnt)
 {
 	int error;
 	int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
@@ -2501,9 +2504,11 @@ int vfs_rename(struct inode *old_dir, st
 	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
 
 	if (is_dir)
-		error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
+		error = vfs_rename_dir(old_dir, old_dentry, old_mnt,
+				       new_dir, new_dentry, new_mnt);
 	else
-		error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
+		error = vfs_rename_other(old_dir, old_dentry, old_mnt,
+					 new_dir, new_dentry, new_mnt);
 	if (!error) {
 		const char *new_name = old_dentry->d_name.name;
 		fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
@@ -2575,8 +2580,8 @@ static int do_rename(int olddfd, const c
 	if (new_dentry == trap)
 		goto exit5;
 
-	error = vfs_rename(old_dir->d_inode, old_dentry,
-				   new_dir->d_inode, new_dentry);
+	error = vfs_rename(old_dir->d_inode, old_dentry, oldnd.mnt,
+			   new_dir->d_inode, new_dentry, newnd.mnt);
 exit5:
 	dput(new_dentry);
 exit4:
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1630,7 +1630,8 @@ nfsd_rename(struct svc_rqst *rqstp, stru
 			host_err = -EPERM;
 	} else
 #endif
-	host_err = vfs_rename(fdir, odentry, tdir, ndentry);
+	host_err = vfs_rename(fdir, odentry, ffhp->fh_export->ex_mnt,
+			      tdir, ndentry, tfhp->fh_export->ex_mnt);
 	if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
 		host_err = nfsd_sync_dir(tdentry);
 		if (!host_err)
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -998,7 +998,7 @@ extern int vfs_symlink(struct inode *, s
 extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
 extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
 extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
-extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
 
 /*
  * VFS dentry helper functions.

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 20/45] Pass struct vfsmount to the inode_rename LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (18 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 19/45] Add struct vfsmount parameters to vfs_rename() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 21/45] Add a struct vfsmount parameter to vfs_setxattr() jjohansen
                   ` (25 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-rename.diff --]
[-- Type: text/plain, Size: 4640 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/namei.c               |    6 ++++--
 include/linux/security.h |   18 +++++++++++++-----
 security/dummy.c         |    4 +++-
 security/selinux/hooks.c |    8 ++++++--
 4 files changed, 26 insertions(+), 10 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2417,7 +2417,8 @@ static int vfs_rename_dir(struct inode *
 			return error;
 	}
 
-	error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
+	error = security_inode_rename(old_dir, old_dentry, old_mnt,
+				      new_dir, new_dentry, new_mnt);
 	if (error)
 		return error;
 
@@ -2451,7 +2452,8 @@ static int vfs_rename_other(struct inode
 	struct inode *target;
 	int error;
 
-	error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
+	error = security_inode_rename(old_dir, old_dentry, old_mnt,
+				      new_dir, new_dentry, new_mnt);
 	if (error)
 		return error;
 
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -336,8 +336,10 @@ struct request_sock;
  *	Check for permission to rename a file or directory.
  *	@old_dir contains the inode structure for parent of the old link.
  *	@old_dentry contains the dentry structure of the old link.
+ *	@old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
  *	@new_dir contains the inode structure for parent of the new link.
  *	@new_dentry contains the dentry structure of the new link.
+ *	@new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
  *	Return 0 if permission is granted.
  * @inode_readlink:
  *	Check the permission to read the symbolic link.
@@ -1230,7 +1232,9 @@ struct security_operations {
 	int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
 			    struct vfsmount *mnt, int mode, dev_t dev);
 	int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
-	                     struct inode *new_dir, struct dentry *new_dentry);
+			     struct vfsmount *old_mnt,
+	                     struct inode *new_dir, struct dentry *new_dentry,
+			     struct vfsmount *new_mnt);
 	int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt);
 	int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
 	int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
@@ -1696,14 +1700,16 @@ static inline int security_inode_mknod (
 
 static inline int security_inode_rename (struct inode *old_dir,
 					 struct dentry *old_dentry,
+					 struct vfsmount *old_mnt,
 					 struct inode *new_dir,
-					 struct dentry *new_dentry)
+					 struct dentry *new_dentry,
+					 struct vfsmount *new_mnt)
 {
         if (unlikely (IS_PRIVATE (old_dentry->d_inode) ||
             (new_dentry->d_inode && IS_PRIVATE (new_dentry->d_inode))))
 		return 0;
-	return security_ops->inode_rename (old_dir, old_dentry,
-					   new_dir, new_dentry);
+	return security_ops->inode_rename (old_dir, old_dentry, old_mnt,
+					   new_dir, new_dentry, new_mnt);
 }
 
 static inline int security_inode_readlink (struct dentry *dentry,
@@ -2419,8 +2425,10 @@ static inline int security_inode_mknod (
 
 static inline int security_inode_rename (struct inode *old_dir,
 					 struct dentry *old_dentry,
+					 struct vfsmount *old_mnt,
 					 struct inode *new_dir,
-					 struct dentry *new_dentry)
+					 struct dentry *new_dentry,
+					 struct vfsmount *new_mnt)
 {
 	return 0;
 }
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -310,8 +310,10 @@ static int dummy_inode_mknod (struct ino
 
 static int dummy_inode_rename (struct inode *old_inode,
 			       struct dentry *old_dentry,
+			       struct vfsmount *old_mnt,
 			       struct inode *new_inode,
-			       struct dentry *new_dentry)
+			       struct dentry *new_dentry,
+			       struct vfsmount *new_mnt)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2238,8 +2238,12 @@ static int selinux_inode_mknod(struct in
 	return may_create(dir, dentry, inode_mode_to_security_class(mode));
 }
 
-static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
-                                struct inode *new_inode, struct dentry *new_dentry)
+static int selinux_inode_rename(struct inode *old_inode,
+				struct dentry *old_dentry,
+				struct vfsmount *old_mnt,
+                                struct inode *new_inode,
+				struct dentry *new_dentry,
+				struct vfsmount *new_mnt)
 {
 	return may_rename(old_inode, old_dentry, new_inode, new_dentry);
 }

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 21/45] Add a struct vfsmount parameter to vfs_setxattr()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (19 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 20/45] Pass struct vfsmount to the inode_rename LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 22/45] Pass struct vfsmount to the inode_setxattr LSM hook jjohansen
                   ` (24 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-setxattr.diff --]
[-- Type: text/plain, Size: 4721 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/nfsd/vfs.c         |   16 +++++++++++-----
 fs/xattr.c            |   16 ++++++++--------
 include/linux/xattr.h |    3 ++-
 3 files changed, 21 insertions(+), 14 deletions(-)

--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -396,7 +396,8 @@ static ssize_t nfsd_getxattr(struct dent
 
 #if defined(CONFIG_NFSD_V4)
 static int
-set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
+set_nfsv4_acl_one(struct dentry *dentry, struct vfsmount *mnt,
+		  struct posix_acl *pacl, char *key)
 {
 	int len;
 	size_t buflen;
@@ -415,7 +416,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
 		goto out;
 	}
 
-	error = vfs_setxattr(dentry, key, buf, len, 0);
+	error = vfs_setxattr(dentry, mnt, key, buf, len, 0);
 out:
 	kfree(buf);
 	return error;
@@ -428,6 +429,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
 	__be32 error;
 	int host_error;
 	struct dentry *dentry;
+	struct vfsmount *mnt;
 	struct inode *inode;
 	struct posix_acl *pacl = NULL, *dpacl = NULL;
 	unsigned int flags = 0;
@@ -438,6 +440,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
 		goto out;
 
 	dentry = fhp->fh_dentry;
+	mnt = fhp->fh_export->ex_mnt;
 	inode = dentry->d_inode;
 	if (S_ISDIR(inode->i_mode))
 		flags = NFS4_ACL_DIR;
@@ -449,12 +452,14 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
 	} else if (host_error < 0)
 		goto out_nfserr;
 
-	host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
+	host_error = set_nfsv4_acl_one(dentry, mnt, pacl,
+				       POSIX_ACL_XATTR_ACCESS);
 	if (host_error < 0)
 		goto out_nfserr;
 
 	if (S_ISDIR(inode->i_mode)) {
-		host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
+		host_error = set_nfsv4_acl_one(dentry, mnt, dpacl,
+					       POSIX_ACL_XATTR_DEFAULT);
 		if (host_error < 0)
 			goto out_nfserr;
 	}
@@ -1982,7 +1987,8 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
 		size = 0;
 
 	if (size)
-		error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
+		error = vfs_setxattr(fhp->fh_dentry, fhp->fh_export->ex_mnt,
+				     name, value, size,0);
 	else {
 		if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
 			error = 0;
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -69,8 +69,8 @@ xattr_permission(struct inode *inode, co
 }
 
 int
-vfs_setxattr(struct dentry *dentry, char *name, void *value,
-		size_t size, int flags)
+vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
+	     void *value, size_t size, int flags)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
@@ -193,8 +193,8 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
  * Extended attribute SET operations
  */
 static long
-setxattr(struct dentry *d, char __user *name, void __user *value,
-	 size_t size, int flags)
+setxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
+	 void __user *value, size_t size, int flags)
 {
 	int error;
 	void *kvalue = NULL;
@@ -221,7 +221,7 @@ setxattr(struct dentry *d, char __user *
 		}
 	}
 
-	error = vfs_setxattr(d, kname, kvalue, size, flags);
+	error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags);
 	kfree(kvalue);
 	return error;
 }
@@ -236,7 +236,7 @@ sys_setxattr(char __user *path, char __u
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = setxattr(nd.dentry, name, value, size, flags);
+	error = setxattr(nd.dentry, nd.mnt, name, value, size, flags);
 	path_release(&nd);
 	return error;
 }
@@ -251,7 +251,7 @@ sys_lsetxattr(char __user *path, char __
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = setxattr(nd.dentry, name, value, size, flags);
+	error = setxattr(nd.dentry, nd.mnt, name, value, size, flags);
 	path_release(&nd);
 	return error;
 }
@@ -269,7 +269,7 @@ sys_fsetxattr(int fd, char __user *name,
 		return error;
 	dentry = f->f_path.dentry;
 	audit_inode(NULL, dentry->d_inode);
-	error = setxattr(dentry, name, value, size, flags);
+	error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags);
 	fput(f);
 	return error;
 }
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -48,7 +48,8 @@ struct xattr_handler {
 
 ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
 ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
-int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
+int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
+		 int);
 int vfs_removexattr(struct dentry *, char *);
 
 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 22/45] Pass struct vfsmount to the inode_setxattr LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (20 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 21/45] Add a struct vfsmount parameter to vfs_setxattr() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 23/45] Add a struct vfsmount parameter to vfs_getxattr() jjohansen
                   ` (23 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-setxattr.diff --]
[-- Type: text/plain, Size: 7658 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/xattr.c               |    4 ++--
 include/linux/security.h |   40 +++++++++++++++++++++++++---------------
 security/commoncap.c     |    4 ++--
 security/dummy.c         |    9 ++++++---
 security/selinux/hooks.c |    8 ++++++--
 5 files changed, 41 insertions(+), 24 deletions(-)

--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -80,7 +80,7 @@ vfs_setxattr(struct dentry *dentry, stru
 		return error;
 
 	mutex_lock(&inode->i_mutex);
-	error = security_inode_setxattr(dentry, name, value, size, flags);
+	error = security_inode_setxattr(dentry, mnt, name, value, size, flags);
 	if (error)
 		goto out;
 	error = -EOPNOTSUPP;
@@ -88,7 +88,7 @@ vfs_setxattr(struct dentry *dentry, stru
 		error = inode->i_op->setxattr(dentry, name, value, size, flags);
 		if (!error) {
 			fsnotify_xattr(dentry);
-			security_inode_post_setxattr(dentry, name, value,
+			security_inode_post_setxattr(dentry, mnt, name, value,
 						     size, flags);
 		}
 	} else if (!strncmp(name, XATTR_SECURITY_PREFIX,
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -49,7 +49,7 @@ extern void cap_capset_set (struct task_
 extern int cap_bprm_set_security (struct linux_binprm *bprm);
 extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
 extern int cap_bprm_secureexec(struct linux_binprm *bprm);
-extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
 extern int cap_inode_removexattr(struct dentry *dentry, char *name);
 extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
 extern void cap_task_reparent_to_init (struct task_struct *p);
@@ -384,11 +384,11 @@ struct request_sock;
  *	inode.
  * @inode_setxattr:
  * 	Check permission before setting the extended attributes
- * 	@value identified by @name for @dentry.
+ * 	@value identified by @name for @dentry and @mnt.
  * 	Return 0 if permission is granted.
  * @inode_post_setxattr:
  * 	Update inode security field after successful setxattr operation.
- * 	@value identified by @name for @dentry.
+ * 	@value identified by @name for @dentry and @mnt.
  * @inode_getxattr:
  * 	Check permission before obtaining the extended attributes
  * 	identified by @name for @dentry.
@@ -1242,9 +1242,11 @@ struct security_operations {
 			      struct iattr *attr);
 	int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
         void (*inode_delete) (struct inode *inode);
-	int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
-			       size_t size, int flags);
-	void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
+	int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
+			       char *name, void *value, size_t size, int flags);
+	void (*inode_post_setxattr) (struct dentry *dentry,
+				     struct vfsmount *mnt,
+				     char *name, void *value,
 				     size_t size, int flags);
 	int (*inode_getxattr) (struct dentry *dentry, char *name);
 	int (*inode_listxattr) (struct dentry *dentry);
@@ -1760,20 +1762,24 @@ static inline void security_inode_delete
 	security_ops->inode_delete (inode);
 }
 
-static inline int security_inode_setxattr (struct dentry *dentry, char *name,
+static inline int security_inode_setxattr (struct dentry *dentry,
+					   struct vfsmount *mnt, char *name,
 					   void *value, size_t size, int flags)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_setxattr (dentry, name, value, size, flags);
+	return security_ops->inode_setxattr (dentry, mnt, name, value, size,
+					     flags);
 }
 
-static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
-						void *value, size_t size, int flags)
+static inline void security_inode_post_setxattr (struct dentry *dentry,
+						 struct vfsmount *mnt,
+						 char *name, void *value,
+						 size_t size, int flags)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return;
-	security_ops->inode_post_setxattr (dentry, name, value, size, flags);
+	security_ops->inode_post_setxattr (dentry, mnt, name, value, size, flags);
 }
 
 static inline int security_inode_getxattr (struct dentry *dentry, char *name)
@@ -2467,14 +2473,18 @@ static inline int security_inode_getattr
 static inline void security_inode_delete (struct inode *inode)
 { }
 
-static inline int security_inode_setxattr (struct dentry *dentry, char *name,
+static inline int security_inode_setxattr (struct dentry *dentry,
+					   struct vfsmount *mnt, char *name,
 					   void *value, size_t size, int flags)
 {
-	return cap_inode_setxattr(dentry, name, value, size, flags);
+	return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
 }
 
-static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
-						 void *value, size_t size, int flags)
+static inline void security_inode_post_setxattr (struct dentry *dentry,
+						 struct vfsmount *mnt,
+						 char *name,
+						 void *value, size_t size,
+						 int flags)
 { }
 
 static inline int security_inode_getxattr (struct dentry *dentry, char *name)
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -190,8 +190,8 @@ int cap_bprm_secureexec (struct linux_bi
 		current->egid != current->gid);
 }
 
-int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
-		       size_t size, int flags)
+int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
+		       void *value, size_t size, int flags)
 {
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 		     sizeof(XATTR_SECURITY_PREFIX) - 1)  &&
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -350,8 +350,9 @@ static void dummy_inode_delete (struct i
 	return;
 }
 
-static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
-				size_t size, int flags)
+static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
+				 char *name, void *value, size_t size,
+				 int flags)
 {
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 		     sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -360,7 +361,9 @@ static int dummy_inode_setxattr (struct 
 	return 0;
 }
 
-static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
+static void dummy_inode_post_setxattr (struct dentry *dentry,
+				       struct vfsmount *mnt,
+				       char *name, void *value,
 				       size_t size, int flags)
 {
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2305,7 +2305,9 @@ static int selinux_inode_getattr(struct 
 	return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
 }
 
-static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
+static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+				  char *name, void *value, size_t size,
+				  int flags)
 {
 	struct task_security_struct *tsec = current->security;
 	struct inode *inode = dentry->d_inode;
@@ -2365,7 +2367,9 @@ static int selinux_inode_setxattr(struct
 			    &ad);
 }
 
-static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+static void selinux_inode_post_setxattr(struct dentry *dentry,
+					struct vfsmount *mnt,
+					char *name,
                                         void *value, size_t size, int flags)
 {
 	struct inode *inode = dentry->d_inode;

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 23/45] Add a struct vfsmount parameter to vfs_getxattr()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (21 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 22/45] Pass struct vfsmount to the inode_setxattr LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 24/45] Pass struct vfsmount to the inode_getxattr LSM hook jjohansen
                   ` (22 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-getxattr.diff --]
[-- Type: text/plain, Size: 6227 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/nfsd/nfs4xdr.c         |    2 +-
 fs/nfsd/vfs.c             |   21 ++++++++++++---------
 fs/xattr.c                |   14 ++++++++------
 include/linux/nfsd/nfsd.h |    3 ++-
 include/linux/xattr.h     |    3 ++-
 5 files changed, 25 insertions(+), 18 deletions(-)

--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1469,7 +1469,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
 	}
 	if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
 			| FATTR4_WORD0_SUPPORTED_ATTRS)) {
-		err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
+		err = nfsd4_get_nfs4_acl(rqstp, dentry, exp->ex_mnt, &acl);
 		aclsupport = (err == 0);
 		if (bmval0 & FATTR4_WORD0_ACL) {
 			if (err == -EOPNOTSUPP)
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -378,11 +378,12 @@ out_nfserr:
 #if defined(CONFIG_NFSD_V2_ACL) || \
     defined(CONFIG_NFSD_V3_ACL) || \
     defined(CONFIG_NFSD_V4)
-static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
+static ssize_t nfsd_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+			     char *key, void **buf)
 {
 	ssize_t buflen;
 
-	buflen = vfs_getxattr(dentry, key, NULL, 0);
+	buflen = vfs_getxattr(dentry, mnt, key, NULL, 0);
 	if (buflen <= 0)
 		return buflen;
 
@@ -390,7 +391,7 @@ static ssize_t nfsd_getxattr(struct dent
 	if (!*buf)
 		return -ENOMEM;
 
-	return vfs_getxattr(dentry, key, *buf, buflen);
+	return vfs_getxattr(dentry, mnt, key, *buf, buflen);
 }
 #endif
 
@@ -479,13 +480,13 @@ out_nfserr:
 }
 
 static struct posix_acl *
-_get_posix_acl(struct dentry *dentry, char *key)
+_get_posix_acl(struct dentry *dentry, struct vfsmount *mnt, char *key)
 {
 	void *buf = NULL;
 	struct posix_acl *pacl = NULL;
 	int buflen;
 
-	buflen = nfsd_getxattr(dentry, key, &buf);
+	buflen = nfsd_getxattr(dentry, mnt, key, &buf);
 	if (!buflen)
 		buflen = -ENODATA;
 	if (buflen <= 0)
@@ -497,14 +498,15 @@ _get_posix_acl(struct dentry *dentry, ch
 }
 
 int
-nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
+nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
+		   struct vfsmount *mnt, struct nfs4_acl **acl)
 {
 	struct inode *inode = dentry->d_inode;
 	int error = 0;
 	struct posix_acl *pacl = NULL, *dpacl = NULL;
 	unsigned int flags = 0;
 
-	pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
+	pacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_ACCESS);
 	if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
 		pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
 	if (IS_ERR(pacl)) {
@@ -514,7 +516,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqst
 	}
 
 	if (S_ISDIR(inode->i_mode)) {
-		dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
+		dpacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_DEFAULT);
 		if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
 			dpacl = NULL;
 		else if (IS_ERR(dpacl)) {
@@ -1942,7 +1944,8 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
 		return ERR_PTR(-EOPNOTSUPP);
 	}
 
-	size = nfsd_getxattr(fhp->fh_dentry, name, &value);
+	size = nfsd_getxattr(fhp->fh_dentry, fhp->fh_export->ex_mnt, name,
+			     &value);
 	if (size < 0)
 		return ERR_PTR(size);
 
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -106,7 +106,8 @@ out:
 EXPORT_SYMBOL_GPL(vfs_setxattr);
 
 ssize_t
-vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
+vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
+	     void *value, size_t size)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
@@ -278,7 +279,8 @@ sys_fsetxattr(int fd, char __user *name,
  * Extended attribute GET operations
  */
 static ssize_t
-getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
+getxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
+	 void __user *value, size_t size)
 {
 	ssize_t error;
 	void *kvalue = NULL;
@@ -298,7 +300,7 @@ getxattr(struct dentry *d, char __user *
 			return -ENOMEM;
 	}
 
-	error = vfs_getxattr(d, kname, kvalue, size);
+	error = vfs_getxattr(dentry, mnt, kname, kvalue, size);
 	if (error > 0) {
 		if (size && copy_to_user(value, kvalue, error))
 			error = -EFAULT;
@@ -321,7 +323,7 @@ sys_getxattr(char __user *path, char __u
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = getxattr(nd.dentry, name, value, size);
+	error = getxattr(nd.dentry, nd.mnt, name, value, size);
 	path_release(&nd);
 	return error;
 }
@@ -336,7 +338,7 @@ sys_lgetxattr(char __user *path, char __
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = getxattr(nd.dentry, name, value, size);
+	error = getxattr(nd.dentry, nd.mnt, name, value, size);
 	path_release(&nd);
 	return error;
 }
@@ -351,7 +353,7 @@ sys_fgetxattr(int fd, char __user *name,
 	if (!f)
 		return error;
 	audit_inode(NULL, f->f_path.dentry->d_inode);
-	error = getxattr(f->f_path.dentry, name, value, size);
+	error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
 	fput(f);
 	return error;
 }
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -77,7 +77,8 @@ __be32		nfsd_setattr(struct svc_rqst *, 
 #ifdef CONFIG_NFSD_V4
 __be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
                     struct nfs4_acl *);
-int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
+int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *,
+				struct vfsmount *mnt, struct nfs4_acl **);
 #endif /* CONFIG_NFSD_V4 */
 __be32		nfsd_create(struct svc_rqst *, struct svc_fh *,
 				char *name, int len, struct iattr *attrs,
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -46,7 +46,8 @@ struct xattr_handler {
 		   size_t size, int flags);
 };
 
-ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
+ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
+		     size_t);
 ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
 int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
 		 int);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 24/45] Pass struct vfsmount to the inode_getxattr LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (22 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 23/45] Add a struct vfsmount parameter to vfs_getxattr() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 25/45] Add a struct vfsmount parameter to vfs_listxattr() jjohansen
                   ` (21 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-getxattr.diff --]
[-- Type: text/plain, Size: 3185 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/xattr.c               |    2 +-
 include/linux/security.h |   13 ++++++++-----
 security/dummy.c         |    3 ++-
 security/selinux/hooks.c |    3 ++-
 4 files changed, 13 insertions(+), 8 deletions(-)

--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -116,7 +116,7 @@ vfs_getxattr(struct dentry *dentry, stru
 	if (error)
 		return error;
 
-	error = security_inode_getxattr(dentry, name);
+	error = security_inode_getxattr(dentry, mnt, name);
 	if (error)
 		return error;
 
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -391,7 +391,7 @@ struct request_sock;
  * 	@value identified by @name for @dentry and @mnt.
  * @inode_getxattr:
  * 	Check permission before obtaining the extended attributes
- * 	identified by @name for @dentry.
+ * 	identified by @name for @dentry and @mnt.
  * 	Return 0 if permission is granted.
  * @inode_listxattr:
  * 	Check permission before obtaining the list of extended attribute 
@@ -1248,7 +1248,8 @@ struct security_operations {
 				     struct vfsmount *mnt,
 				     char *name, void *value,
 				     size_t size, int flags);
-	int (*inode_getxattr) (struct dentry *dentry, char *name);
+	int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
+			       char *name);
 	int (*inode_listxattr) (struct dentry *dentry);
 	int (*inode_removexattr) (struct dentry *dentry, char *name);
 	const char *(*inode_xattr_getsuffix) (void);
@@ -1782,11 +1783,12 @@ static inline void security_inode_post_s
 	security_ops->inode_post_setxattr (dentry, mnt, name, value, size, flags);
 }
 
-static inline int security_inode_getxattr (struct dentry *dentry, char *name)
+static inline int security_inode_getxattr (struct dentry *dentry,
+					    struct vfsmount *mnt, char *name)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_getxattr (dentry, name);
+	return security_ops->inode_getxattr (dentry, mnt, name);
 }
 
 static inline int security_inode_listxattr (struct dentry *dentry)
@@ -2487,7 +2489,8 @@ static inline void security_inode_post_s
 						 int flags)
 { }
 
-static inline int security_inode_getxattr (struct dentry *dentry, char *name)
+static inline int security_inode_getxattr (struct dentry *dentry,
+					    struct vfsmount *mnt, char *name)
 {
 	return 0;
 }
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -368,7 +368,8 @@ static void dummy_inode_post_setxattr (s
 {
 }
 
-static int dummy_inode_getxattr (struct dentry *dentry, char *name)
+static int dummy_inode_getxattr (struct dentry *dentry,
+			          struct vfsmount *mnt, char *name)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2393,7 +2393,8 @@ static void selinux_inode_post_setxattr(
 	return;
 }
 
-static int selinux_inode_getxattr (struct dentry *dentry, char *name)
+static int selinux_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt,
+				   char *name)
 {
 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 25/45] Add a struct vfsmount parameter to vfs_listxattr()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (23 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 24/45] Pass struct vfsmount to the inode_getxattr LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 26/45] Pass struct vfsmount to the inode_listxattr LSM hook jjohansen
                   ` (20 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-listxattr.diff --]
[-- Type: text/plain, Size: 3170 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/xattr.c            |   25 ++++++++++++++-----------
 include/linux/xattr.h |    3 ++-
 2 files changed, 16 insertions(+), 12 deletions(-)

--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -143,18 +143,20 @@ vfs_getxattr(struct dentry *dentry, stru
 EXPORT_SYMBOL_GPL(vfs_getxattr);
 
 ssize_t
-vfs_listxattr(struct dentry *d, char *list, size_t size)
+vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
+	      size_t size)
 {
+	struct inode *inode = dentry->d_inode;
 	ssize_t error;
 
-	error = security_inode_listxattr(d);
+	error = security_inode_listxattr(dentry);
 	if (error)
 		return error;
 	error = -EOPNOTSUPP;
-	if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
-		error = d->d_inode->i_op->listxattr(d, list, size);
-	} else {
-		error = security_inode_listsecurity(d->d_inode, list, size);
+	if (inode->i_op && inode->i_op->listxattr)
+		error = inode->i_op->listxattr(dentry, list, size);
+	else {
+		error = security_inode_listsecurity(inode, list, size);
 		if (size && error > size)
 			error = -ERANGE;
 	}
@@ -362,7 +364,8 @@ sys_fgetxattr(int fd, char __user *name,
  * Extended attribute LIST operations
  */
 static ssize_t
-listxattr(struct dentry *d, char __user *list, size_t size)
+listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
+	  size_t size)
 {
 	ssize_t error;
 	char *klist = NULL;
@@ -375,7 +378,7 @@ listxattr(struct dentry *d, char __user 
 			return -ENOMEM;
 	}
 
-	error = vfs_listxattr(d, klist, size);
+	error = vfs_listxattr(dentry, mnt, klist, size);
 	if (error > 0) {
 		if (size && copy_to_user(list, klist, error))
 			error = -EFAULT;
@@ -397,7 +400,7 @@ sys_listxattr(char __user *path, char __
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = listxattr(nd.dentry, list, size);
+	error = listxattr(nd.dentry, nd.mnt, list, size);
 	path_release(&nd);
 	return error;
 }
@@ -411,7 +414,7 @@ sys_llistxattr(char __user *path, char _
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = listxattr(nd.dentry, list, size);
+	error = listxattr(nd.dentry, nd.mnt, list, size);
 	path_release(&nd);
 	return error;
 }
@@ -426,7 +429,7 @@ sys_flistxattr(int fd, char __user *list
 	if (!f)
 		return error;
 	audit_inode(NULL, f->f_path.dentry->d_inode);
-	error = listxattr(f->f_path.dentry, list, size);
+	error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
 	fput(f);
 	return error;
 }
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -48,7 +48,8 @@ struct xattr_handler {
 
 ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
 		     size_t);
-ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
+ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list,
+		      size_t size);
 int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
 		 int);
 int vfs_removexattr(struct dentry *, char *);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 26/45] Pass struct vfsmount to the inode_listxattr LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (24 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 25/45] Add a struct vfsmount parameter to vfs_listxattr() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 27/45] Add a struct vfsmount parameter to vfs_removexattr() jjohansen
                   ` (19 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-listxattr.diff --]
[-- Type: text/plain, Size: 3165 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/xattr.c               |    2 +-
 include/linux/security.h |   12 +++++++-----
 security/dummy.c         |    2 +-
 security/selinux/hooks.c |    2 +-
 4 files changed, 10 insertions(+), 8 deletions(-)

--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -149,7 +149,7 @@ vfs_listxattr(struct dentry *dentry, str
 	struct inode *inode = dentry->d_inode;
 	ssize_t error;
 
-	error = security_inode_listxattr(dentry);
+	error = security_inode_listxattr(dentry, mnt);
 	if (error)
 		return error;
 	error = -EOPNOTSUPP;
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -395,7 +395,7 @@ struct request_sock;
  * 	Return 0 if permission is granted.
  * @inode_listxattr:
  * 	Check permission before obtaining the list of extended attribute 
- * 	names for @dentry.
+ * 	names for @dentry and @mnt.
  * 	Return 0 if permission is granted.
  * @inode_removexattr:
  * 	Check permission before removing the extended attribute
@@ -1250,7 +1250,7 @@ struct security_operations {
 				     size_t size, int flags);
 	int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
 			       char *name);
-	int (*inode_listxattr) (struct dentry *dentry);
+	int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
 	int (*inode_removexattr) (struct dentry *dentry, char *name);
 	const char *(*inode_xattr_getsuffix) (void);
   	int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
@@ -1791,11 +1791,12 @@ static inline int security_inode_getxatt
 	return security_ops->inode_getxattr (dentry, mnt, name);
 }
 
-static inline int security_inode_listxattr (struct dentry *dentry)
+static inline int security_inode_listxattr (struct dentry *dentry,
+					    struct vfsmount *mnt)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_listxattr (dentry);
+	return security_ops->inode_listxattr (dentry, mnt);
 }
 
 static inline int security_inode_removexattr (struct dentry *dentry, char *name)
@@ -2495,7 +2496,8 @@ static inline int security_inode_getxatt
 	return 0;
 }
 
-static inline int security_inode_listxattr (struct dentry *dentry)
+static inline int security_inode_listxattr (struct dentry *dentry,
+					    struct vfsmount *mnt)
 {
 	return 0;
 }
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -374,7 +374,7 @@ static int dummy_inode_getxattr (struct 
 	return 0;
 }
 
-static int dummy_inode_listxattr (struct dentry *dentry)
+static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
 {
 	return 0;
 }
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2399,7 +2399,7 @@ static int selinux_inode_getxattr (struc
 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
 
-static int selinux_inode_listxattr (struct dentry *dentry)
+static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
 {
 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 27/45] Add a struct vfsmount parameter to vfs_removexattr()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (25 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 26/45] Pass struct vfsmount to the inode_listxattr LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 28/45] Pass struct vfsmount to the inode_removexattr LSM hook jjohansen
                   ` (18 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: vfs-removexattr.diff --]
[-- Type: text/plain, Size: 3364 bytes --]

The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/nfsd/vfs.c         |    7 ++++---
 fs/xattr.c            |   12 ++++++------
 include/linux/xattr.h |    2 +-
 3 files changed, 11 insertions(+), 10 deletions(-)

--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1957,6 +1957,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
 int
 nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
 {
+	struct vfsmount *mnt;
 	struct inode *inode = fhp->fh_dentry->d_inode;
 	char *name;
 	void *value = NULL;
@@ -1989,14 +1990,14 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
 	} else
 		size = 0;
 
+	mnt = fhp->fh_export->ex_mnt;
 	if (size)
-		error = vfs_setxattr(fhp->fh_dentry, fhp->fh_export->ex_mnt,
-				     name, value, size,0);
+		error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size,0);
 	else {
 		if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
 			error = 0;
 		else {
-			error = vfs_removexattr(fhp->fh_dentry, name);
+			error = vfs_removexattr(fhp->fh_dentry, mnt, name);
 			if (error == -ENODATA)
 				error = 0;
 		}
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -165,7 +165,7 @@ vfs_listxattr(struct dentry *dentry, str
 EXPORT_SYMBOL_GPL(vfs_listxattr);
 
 int
-vfs_removexattr(struct dentry *dentry, char *name)
+vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
@@ -438,7 +438,7 @@ sys_flistxattr(int fd, char __user *list
  * Extended attribute REMOVE operations
  */
 static long
-removexattr(struct dentry *d, char __user *name)
+removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name)
 {
 	int error;
 	char kname[XATTR_NAME_MAX + 1];
@@ -449,7 +449,7 @@ removexattr(struct dentry *d, char __use
 	if (error < 0)
 		return error;
 
-	return vfs_removexattr(d, kname);
+	return vfs_removexattr(dentry, mnt, kname);
 }
 
 asmlinkage long
@@ -461,7 +461,7 @@ sys_removexattr(char __user *path, char 
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = removexattr(nd.dentry, name);
+	error = removexattr(nd.dentry, nd.mnt, name);
 	path_release(&nd);
 	return error;
 }
@@ -475,7 +475,7 @@ sys_lremovexattr(char __user *path, char
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = removexattr(nd.dentry, name);
+	error = removexattr(nd.dentry, nd.mnt, name);
 	path_release(&nd);
 	return error;
 }
@@ -492,7 +492,7 @@ sys_fremovexattr(int fd, char __user *na
 		return error;
 	dentry = f->f_path.dentry;
 	audit_inode(NULL, dentry->d_inode);
-	error = removexattr(dentry, name);
+	error = removexattr(dentry, f->f_path.mnt, name);
 	fput(f);
 	return error;
 }
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -52,7 +52,7 @@ ssize_t vfs_listxattr(struct dentry *d, 
 		      size_t size);
 int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
 		 int);
-int vfs_removexattr(struct dentry *, char *);
+int vfs_removexattr(struct dentry *, struct vfsmount *, char *);
 
 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 28/45] Pass struct vfsmount to the inode_removexattr LSM hook
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (26 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 27/45] Add a struct vfsmount parameter to vfs_removexattr() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 29/45] Fix __d_path() for lazy unmounts and make it unambiguous jjohansen
                   ` (17 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Tony Jones,
	Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-removexattr.diff --]
[-- Type: text/plain, Size: 4369 bytes --]

This is needed for computing pathnames in the AppArmor LSM.

Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/xattr.c               |    2 +-
 include/linux/security.h |   15 +++++++++------
 security/commoncap.c     |    3 ++-
 security/dummy.c         |    3 ++-
 security/selinux/hooks.c |    3 ++-
 5 files changed, 16 insertions(+), 10 deletions(-)

--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -177,7 +177,7 @@ vfs_removexattr(struct dentry *dentry, s
 	if (error)
 		return error;
 
-	error = security_inode_removexattr(dentry, name);
+	error = security_inode_removexattr(dentry, mnt, name);
 	if (error)
 		return error;
 
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -50,7 +50,7 @@ extern int cap_bprm_set_security (struct
 extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
 extern int cap_bprm_secureexec(struct linux_binprm *bprm);
 extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, char *name);
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name);
 extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
 extern void cap_task_reparent_to_init (struct task_struct *p);
 extern int cap_syslog (int type);
@@ -1251,7 +1251,8 @@ struct security_operations {
 	int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
 			       char *name);
 	int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
-	int (*inode_removexattr) (struct dentry *dentry, char *name);
+	int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
+				  char *name);
 	const char *(*inode_xattr_getsuffix) (void);
   	int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
   	int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
@@ -1799,11 +1800,12 @@ static inline int security_inode_listxat
 	return security_ops->inode_listxattr (dentry, mnt);
 }
 
-static inline int security_inode_removexattr (struct dentry *dentry, char *name)
+static inline int security_inode_removexattr (struct dentry *dentry,
+					      struct vfsmount *mnt, char *name)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_removexattr (dentry, name);
+	return security_ops->inode_removexattr (dentry, mnt, name);
 }
 
 static inline const char *security_inode_xattr_getsuffix(void)
@@ -2502,9 +2504,10 @@ static inline int security_inode_listxat
 	return 0;
 }
 
-static inline int security_inode_removexattr (struct dentry *dentry, char *name)
+static inline int security_inode_removexattr (struct dentry *dentry,
+					      struct vfsmount *mnt, char *name)
 {
-	return cap_inode_removexattr(dentry, name);
+	return cap_inode_removexattr(dentry, mnt, name);
 }
 
 static inline const char *security_inode_xattr_getsuffix (void)
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -200,7 +200,8 @@ int cap_inode_setxattr(struct dentry *de
 	return 0;
 }
 
-int cap_inode_removexattr(struct dentry *dentry, char *name)
+int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+			  char *name)
 {
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 		     sizeof(XATTR_SECURITY_PREFIX) - 1)  &&
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -379,7 +379,8 @@ static int dummy_inode_listxattr (struct
 	return 0;
 }
 
-static int dummy_inode_removexattr (struct dentry *dentry, char *name)
+static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
+				    char *name)
 {
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 		     sizeof(XATTR_SECURITY_PREFIX) - 1) &&
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2404,7 +2404,8 @@ static int selinux_inode_listxattr (stru
 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
 
-static int selinux_inode_removexattr (struct dentry *dentry, char *name)
+static int selinux_inode_removexattr (struct dentry *dentry,
+				      struct vfsmount *mnt, char *name)
 {
 	if (strcmp(name, XATTR_NAME_SELINUX)) {
 		if (!strncmp(name, XATTR_SECURITY_PREFIX,

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 29/45] Fix __d_path() for lazy unmounts and make it unambiguous
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (27 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 28/45] Pass struct vfsmount to the inode_removexattr LSM hook jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 30/45] Make d_path() consistent across mount operations jjohansen
                   ` (16 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher, Alan Cox

[-- Attachment #1: unambiguous-__d_path.diff --]
[-- Type: text/plain, Size: 7803 bytes --]

First, when __d_path() hits a lazily unmounted mount point, it tries to prepend
the name of the lazily unmounted dentry to the path name.  It gets this wrong,
and also overwrites the slash that separates the name from the following
pathname component. This patch fixes that; if a process was in directory
/foo/bar and /foo got lazily unmounted, the old result was ``foobar'' (note the
missing slash), while the new result with this patch is ``foo/bar''.

Second, it isn't always possible to tell from the __d_path() result whether the
specified root and rootmnt (i.e., the chroot) was reached.  We need an
unambiguous result for AppArmor at least though, so we make sure that paths
will only start with a slash if the path leads all the way up to the root.

We also add a @fail_deleted argument, which allows to get rid of some of the
mess in sys_getcwd().

This patch leaves getcwd() and d_path() as they were before for everything
except for bind-mounted directories; for them, it reports ``/foo/bar'' instead
of ``foobar'' in the example described above.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>

---
 fs/dcache.c |  169 ++++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 98 insertions(+), 71 deletions(-)

--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1761,52 +1761,51 @@ shouldnt_be_hashed:
 }
 
 /**
- * d_path - return the path of a dentry
+ * __d_path - return the path of a dentry
  * @dentry: dentry to report
  * @vfsmnt: vfsmnt to which the dentry belongs
  * @root: root dentry
  * @rootmnt: vfsmnt to which the root dentry belongs
  * @buffer: buffer to return value in
  * @buflen: buffer length
+ * @fail_deleted: what to return for deleted files
  *
- * Convert a dentry into an ASCII path name. If the entry has been deleted
+ * Convert a dentry into an ASCII path name. If the entry has been deleted,
+ * then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
  * the string " (deleted)" is appended. Note that this is ambiguous.
  *
- * Returns the buffer or an error code if the path was too long.
+ * If @dentry is not connected to @root, the path returned will be relative
+ * (i.e., it will not start with a slash).
  *
- * "buflen" should be positive. Caller holds the dcache_lock.
+ * Returns the buffer or an error code.
  */
-static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
-			struct dentry *root, struct vfsmount *rootmnt,
-			char *buffer, int buflen)
-{
-	char * end = buffer+buflen;
-	char * retval;
-	int namelen;
+static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+		      struct dentry *root, struct vfsmount *rootmnt,
+		      char *buffer, int buflen, int fail_deleted)
+{
+	int namelen, is_slash;
+
+	if (buflen < 2)
+		return ERR_PTR(-ENAMETOOLONG);
+	buffer += --buflen;
+	*buffer = '\0';
 
-	*--end = '\0';
-	buflen--;
+	spin_lock(&dcache_lock);
 	if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
-		buflen -= 10;
-		end -= 10;
-		if (buflen < 0)
+		if (fail_deleted) {
+			buffer = ERR_PTR(-ENOENT);
+			goto out;
+		}
+		if (buflen < 10)
 			goto Elong;
-		memcpy(end, " (deleted)", 10);
+		buflen -= 10;
+		buffer -= 10;
+		memcpy(buffer, " (deleted)", 10);
 	}
-
-	if (buflen < 1)
-		goto Elong;
-	/* Get '/' right */
-	retval = end-1;
-	*retval = '/';
-
-	for (;;) {
+	while (dentry != root || vfsmnt != rootmnt) {
 		struct dentry * parent;
 
-		if (dentry == root && vfsmnt == rootmnt)
-			break;
 		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
-			/* Global root? */
 			spin_lock(&vfsmount_lock);
 			if (vfsmnt->mnt_parent == vfsmnt) {
 				spin_unlock(&vfsmount_lock);
@@ -1820,33 +1819,72 @@ static char * __d_path( struct dentry *d
 		parent = dentry->d_parent;
 		prefetch(parent);
 		namelen = dentry->d_name.len;
-		buflen -= namelen + 1;
-		if (buflen < 0)
+		if (buflen < namelen + 1)
 			goto Elong;
-		end -= namelen;
-		memcpy(end, dentry->d_name.name, namelen);
-		*--end = '/';
-		retval = end;
+		buflen -= namelen + 1;
+		buffer -= namelen;
+		memcpy(buffer, dentry->d_name.name, namelen);
+		*--buffer = '/';
 		dentry = parent;
 	}
+	/* Get '/' right. */
+	if (*buffer != '/')
+		*--buffer = '/';
 
-	return retval;
+out:
+	spin_unlock(&dcache_lock);
+	return buffer;
 
 global_root:
+	/*
+	 * We went past the (vfsmount, dentry) we were looking for and have
+	 * either hit a root dentry, a lazily unmounted dentry, an
+	 * unconnected dentry, or the file is on a pseudo filesystem.
+	 */
 	namelen = dentry->d_name.len;
-	buflen -= namelen;
-	if (buflen < 0)
+	is_slash = (namelen == 1 && *dentry->d_name.name == '/');
+	if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
+		/*
+		 * Make sure we won't return a pathname starting with '/'.
+		 *
+		 * Historically, we also glue together the root dentry and
+		 * remaining name for pseudo filesystems like pipefs, which
+		 * have the MS_NOUSER flag set. This results in pathnames
+		 * like "pipe:[439336]".
+		 */
+		if (*buffer == '/') {
+			buffer++;
+			buflen++;
+		}
+		if (is_slash)
+			goto out;
+	}
+	if (buflen < namelen)
 		goto Elong;
-	retval -= namelen-1;	/* hit the slash */
-	memcpy(retval, dentry->d_name.name, namelen);
-	return retval;
+	buffer -= namelen;
+	memcpy(buffer, dentry->d_name.name, namelen);
+	goto out;
+
 Elong:
-	return ERR_PTR(-ENAMETOOLONG);
+	buffer = ERR_PTR(-ENAMETOOLONG);
+	goto out;
+}
+
+static char *__connect_d_path(char *path, char *buffer)
+{
+	if (!IS_ERR(path) && *path != '/') {
+		/* Pretend that disconnected paths are hanging off the root. */
+		if (path == buffer)
+			path = ERR_PTR(-ENAMETOOLONG);
+		else
+			*--path = '/';
+	}
+	return path;
 }
 
 /* write full pathname into buffer and return start of pathname */
-char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
-				char *buf, int buflen)
+char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
+	     int buflen)
 {
 	char *res;
 	struct vfsmount *rootmnt;
@@ -1866,9 +1904,8 @@ char * d_path(struct dentry *dentry, str
 	rootmnt = mntget(current->fs->rootmnt);
 	root = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
-	spin_lock(&dcache_lock);
-	res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
-	spin_unlock(&dcache_lock);
+	res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
+	res = __connect_d_path(res, buf);
 	dput(root);
 	mntput(rootmnt);
 	return res;
@@ -1915,10 +1952,10 @@ char *dynamic_dname(struct dentry *dentr
  */
 asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
 {
-	int error;
+	int error, len;
 	struct vfsmount *pwdmnt, *rootmnt;
 	struct dentry *pwd, *root;
-	char *page = (char *) __get_free_page(GFP_USER);
+	char *page = (char *) __get_free_page(GFP_USER), *cwd;
 
 	if (!page)
 		return -ENOMEM;
@@ -1930,29 +1967,19 @@ asmlinkage long sys_getcwd(char __user *
 	root = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
 
-	error = -ENOENT;
-	/* Has the current directory has been unlinked? */
-	spin_lock(&dcache_lock);
-	if (pwd->d_parent == pwd || !d_unhashed(pwd)) {
-		unsigned long len;
-		char * cwd;
-
-		cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
-		spin_unlock(&dcache_lock);
-
-		error = PTR_ERR(cwd);
-		if (IS_ERR(cwd))
-			goto out;
-
-		error = -ERANGE;
-		len = PAGE_SIZE + page - cwd;
-		if (len <= size) {
-			error = len;
-			if (copy_to_user(buf, cwd, len))
-				error = -EFAULT;
-		}
-	} else
-		spin_unlock(&dcache_lock);
+	cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
+	cwd = __connect_d_path(cwd, page);
+	error = PTR_ERR(cwd);
+	if (IS_ERR(cwd))
+		goto out;
+
+	error = -ERANGE;
+	len = PAGE_SIZE + page - cwd;
+	if (len <= size) {
+		error = len;
+		if (copy_to_user(buf, cwd, len))
+			error = -EFAULT;
+	}
 
 out:
 	dput(pwd);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 30/45] Make d_path() consistent across mount operations
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (28 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 29/45] Fix __d_path() for lazy unmounts and make it unambiguous jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 31/45] Add d_namespace_path() to compute namespace relative pathnames jjohansen
                   ` (15 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher

[-- Attachment #1: mount-consistent-__d_path.diff --]
[-- Type: text/plain, Size: 1798 bytes --]

The path that __d_path() computes can become slightly inconsistent when it
races with mount operations: it grabs the vfsmount_lock when traversing mount
points but immediately drops it again, only to re-grab it when it reaches the
next mount point.  The result is that the filename computed is not always
consisent, and the file may never have had that name. (This is unlikely, but
still possible.)

Fix this by grabbing the vfsmount_lock when the first mount point is reached,
and holding onto it until the d_cache lookup is completed.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 fs/dcache.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1783,7 +1783,7 @@ static char *__d_path(struct dentry *den
 		      struct dentry *root, struct vfsmount *rootmnt,
 		      char *buffer, int buflen, int fail_deleted)
 {
-	int namelen, is_slash;
+	int namelen, is_slash, vfsmount_locked = 0;
 
 	if (buflen < 2)
 		return ERR_PTR(-ENAMETOOLONG);
@@ -1806,14 +1806,14 @@ static char *__d_path(struct dentry *den
 		struct dentry * parent;
 
 		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
-			spin_lock(&vfsmount_lock);
-			if (vfsmnt->mnt_parent == vfsmnt) {
-				spin_unlock(&vfsmount_lock);
-				goto global_root;
+			if (!vfsmount_locked) {
+				spin_lock(&vfsmount_lock);
+				vfsmount_locked = 1;
 			}
+			if (vfsmnt->mnt_parent == vfsmnt)
+				goto global_root;
 			dentry = vfsmnt->mnt_mountpoint;
 			vfsmnt = vfsmnt->mnt_parent;
-			spin_unlock(&vfsmount_lock);
 			continue;
 		}
 		parent = dentry->d_parent;
@@ -1832,6 +1832,8 @@ static char *__d_path(struct dentry *den
 		*--buffer = '/';
 
 out:
+	if (vfsmount_locked)
+		spin_unlock(&vfsmount_lock);
 	spin_unlock(&dcache_lock);
 	return buffer;
 

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 31/45] Add d_namespace_path() to compute namespace relative pathnames
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (29 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 30/45] Make d_path() consistent across mount operations jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 32/45] Enable LSM hooks to distinguish operations on file descriptors from operations on pathnames jjohansen
                   ` (14 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher

[-- Attachment #1: d_namespace_path.diff --]
[-- Type: text/plain, Size: 2744 bytes --]

In AppArmor, we are interested in pathnames relative to the namespace root.
This is the same as d_path() except for the root where the search ends. Add
a function for computing the namespace-relative path.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Reviewed-by: John Johansen <jjohansen@suse.de>

---
 fs/dcache.c            |    6 +++---
 fs/namespace.c         |   27 +++++++++++++++++++++++++++
 include/linux/dcache.h |    2 ++
 include/linux/mount.h  |    2 ++
 4 files changed, 34 insertions(+), 3 deletions(-)

--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1779,9 +1779,9 @@ shouldnt_be_hashed:
  *
  * Returns the buffer or an error code.
  */
-static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
-		      struct dentry *root, struct vfsmount *rootmnt,
-		      char *buffer, int buflen, int fail_deleted)
+char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+	       struct dentry *root, struct vfsmount *rootmnt,
+	       char *buffer, int buflen, int fail_deleted)
 {
 	int namelen, is_slash, vfsmount_locked = 0;
 
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1868,3 +1868,30 @@ void __put_mnt_ns(struct mnt_namespace *
 	release_mounts(&umount_list);
 	kfree(ns);
 }
+
+char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+		       char *buf, int buflen)
+{
+	struct vfsmount *rootmnt, *nsrootmnt = NULL;
+	struct dentry *root = NULL;
+	char *res;
+
+	read_lock(&current->fs->lock);
+	rootmnt = mntget(current->fs->rootmnt);
+	read_unlock(&current->fs->lock);
+	spin_lock(&vfsmount_lock);
+	if (rootmnt->mnt_ns)
+		nsrootmnt = mntget(rootmnt->mnt_ns->root);
+	spin_unlock(&vfsmount_lock);
+	mntput(rootmnt);
+	if (nsrootmnt)
+		root = dget(nsrootmnt->mnt_root);
+	res = __d_path(dentry, vfsmnt, root, nsrootmnt, buf, buflen, 1);
+	dput(root);
+	mntput(nsrootmnt);
+	/* Prevent empty path for lazily unmounted filesystems. */
+	if (!IS_ERR(res) && *res == '\0')
+		*--res = '.';
+	return res;
+}
+EXPORT_SYMBOL(d_namespace_path);
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -299,6 +299,8 @@ extern int d_validate(struct dentry *, s
  */
 extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
 
+extern char *__d_path(struct dentry *, struct vfsmount *, struct dentry *,
+		      struct vfsmount *, char *, int, int);
 extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
   
 /* Allocation counts.. */
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -103,5 +103,7 @@ extern void shrink_submounts(struct vfsm
 extern spinlock_t vfsmount_lock;
 extern dev_t name_to_dev_t(char *name);
 
+extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
+
 #endif
 #endif /* _LINUX_MOUNT_H */

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 32/45] Enable LSM hooks to distinguish operations on file descriptors from operations on pathnames
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (30 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 31/45] Add d_namespace_path() to compute namespace relative pathnames jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 33/45] Pass struct file down the inode_*xattr security LSM hooks jjohansen
                   ` (13 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher,
	John Johansen, Miklos Szeredi

[-- Attachment #1: file-handle-ops.diff --]
[-- Type: text/plain, Size: 4457 bytes --]

Struct iattr already contains ia_file since commit cc4e69de from 
Miklos (which is related to commit befc649c). Use this to pass
struct file down the setattr hooks. This allows LSMs to distinguish
operations on file descriptors from operations on paths.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
Cc: Miklos Szeredi <mszeredi@suse.cz>

---
 fs/nfsd/vfs.c      |   12 +++++++-----
 fs/open.c          |   16 +++++++++++-----
 include/linux/fs.h |    3 +++
 3 files changed, 21 insertions(+), 10 deletions(-)

--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -383,7 +383,7 @@ static ssize_t nfsd_getxattr(struct dent
 {
 	ssize_t buflen;
 
-	buflen = vfs_getxattr(dentry, mnt, key, NULL, 0);
+	buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
 	if (buflen <= 0)
 		return buflen;
 
@@ -391,7 +391,7 @@ static ssize_t nfsd_getxattr(struct dent
 	if (!*buf)
 		return -ENOMEM;
 
-	return vfs_getxattr(dentry, mnt, key, *buf, buflen);
+	return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
 }
 #endif
 
@@ -417,7 +417,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
 		goto out;
 	}
 
-	error = vfs_setxattr(dentry, mnt, key, buf, len, 0);
+	error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
 out:
 	kfree(buf);
 	return error;
@@ -1992,12 +1992,14 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
 
 	mnt = fhp->fh_export->ex_mnt;
 	if (size)
-		error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size,0);
+		error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
+				     NULL);
 	else {
 		if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
 			error = 0;
 		else {
-			error = vfs_removexattr(fhp->fh_dentry, mnt, name);
+			error = vfs_removexattr(fhp->fh_dentry, mnt, name,
+						NULL);
 			if (error == -ENODATA)
 				error = 0;
 		}
--- a/fs/open.c
+++ b/fs/open.c
@@ -522,6 +522,8 @@ asmlinkage long sys_fchmod(unsigned int 
 		mode = inode->i_mode;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+	newattrs.ia_valid |= ATTR_FILE;
+	newattrs.ia_file = file;
 	err = notify_change(dentry, file->f_path.mnt, &newattrs);
 	mutex_unlock(&inode->i_mutex);
 
@@ -572,7 +574,7 @@ asmlinkage long sys_chmod(const char __u
 }
 
 static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
-			uid_t user, gid_t group)
+			uid_t user, gid_t group, struct file *file)
 {
 	struct inode * inode;
 	int error;
@@ -600,6 +602,10 @@ static int chown_common(struct dentry * 
 	}
 	if (!S_ISDIR(inode->i_mode))
 		newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID;
+	if (file) {
+		newattrs.ia_file = file;
+		newattrs.ia_valid |= ATTR_FILE;
+	}
 	mutex_lock(&inode->i_mutex);
 	error = notify_change(dentry, mnt, &newattrs);
 	mutex_unlock(&inode->i_mutex);
@@ -615,7 +621,7 @@ asmlinkage long sys_chown(const char __u
 	error = user_path_walk(filename, &nd);
 	if (error)
 		goto out;
-	error = chown_common(nd.dentry, nd.mnt, user, group);
+	error = chown_common(nd.dentry, nd.mnt, user, group, NULL);
 	path_release(&nd);
 out:
 	return error;
@@ -635,7 +641,7 @@ asmlinkage long sys_fchownat(int dfd, co
 	error = __user_walk_fd(dfd, filename, follow, &nd);
 	if (error)
 		goto out;
-	error = chown_common(nd.dentry, nd.mnt, user, group);
+	error = chown_common(nd.dentry, nd.mnt, user, group, NULL);
 	path_release(&nd);
 out:
 	return error;
@@ -649,7 +655,7 @@ asmlinkage long sys_lchown(const char __
 	error = user_path_walk_link(filename, &nd);
 	if (error)
 		goto out;
-	error = chown_common(nd.dentry, nd.mnt, user, group);
+	error = chown_common(nd.dentry, nd.mnt, user, group, NULL);
 	path_release(&nd);
 out:
 	return error;
@@ -668,7 +674,7 @@ asmlinkage long sys_fchown(unsigned int 
 
 	dentry = file->f_path.dentry;
 	audit_inode(NULL, dentry->d_inode);
-	error = chown_common(dentry, file->f_path.mnt, user, group);
+	error = chown_common(dentry, file->f_path.mnt, user, group, file);
 	fput(file);
 out:
 	return error;
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -351,6 +351,9 @@ struct iattr {
 	 * Not an attribute, but an auxilary info for filesystems wanting to
 	 * implement an ftruncate() like method.  NOTE: filesystem should
 	 * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
+	 *
+	 * The LSM hooks also use this to distinguish operations on a file
+	 * descriptors from operations on pathnames.
 	 */
 	struct file	*ia_file;
 };

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 33/45] Pass struct file down the inode_*xattr security LSM hooks
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (31 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 32/45] Enable LSM hooks to distinguish operations on file descriptors from operations on pathnames jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 34/45] Factor out sysctl pathname code jjohansen
                   ` (12 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher, John Johansen

[-- Attachment #1: security-xattr-file.diff --]
[-- Type: text/plain, Size: 17988 bytes --]

This allows LSMs to also distinguish between file descriptor and path
access for the xattr operations. (The other relevant operations are
covered by the setattr hook.)

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 fs/xattr.c               |   58 ++++++++++++++++++++++++-----------------------
 include/linux/security.h |   53 +++++++++++++++++++++++++-----------------
 include/linux/xattr.h    |    8 +++---
 security/commoncap.c     |    4 +--
 security/dummy.c         |   10 ++++----
 security/selinux/hooks.c |   10 ++++----
 6 files changed, 80 insertions(+), 63 deletions(-)

--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -70,7 +70,7 @@ xattr_permission(struct inode *inode, co
 
 int
 vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
-	     void *value, size_t size, int flags)
+	     void *value, size_t size, int flags, struct file *file)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
@@ -80,7 +80,7 @@ vfs_setxattr(struct dentry *dentry, stru
 		return error;
 
 	mutex_lock(&inode->i_mutex);
-	error = security_inode_setxattr(dentry, mnt, name, value, size, flags);
+	error = security_inode_setxattr(dentry, mnt, name, value, size, flags,						file);
 	if (error)
 		goto out;
 	error = -EOPNOTSUPP;
@@ -107,7 +107,7 @@ EXPORT_SYMBOL_GPL(vfs_setxattr);
 
 ssize_t
 vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
-	     void *value, size_t size)
+	     void *value, size_t size, struct file *file)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
@@ -116,7 +116,7 @@ vfs_getxattr(struct dentry *dentry, stru
 	if (error)
 		return error;
 
-	error = security_inode_getxattr(dentry, mnt, name);
+	error = security_inode_getxattr(dentry, mnt, name, file);
 	if (error)
 		return error;
 
@@ -144,12 +144,12 @@ EXPORT_SYMBOL_GPL(vfs_getxattr);
 
 ssize_t
 vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
-	      size_t size)
+	      size_t size, struct file *file)
 {
 	struct inode *inode = dentry->d_inode;
 	ssize_t error;
 
-	error = security_inode_listxattr(dentry, mnt);
+	error = security_inode_listxattr(dentry, mnt, file);
 	if (error)
 		return error;
 	error = -EOPNOTSUPP;
@@ -165,7 +165,8 @@ vfs_listxattr(struct dentry *dentry, str
 EXPORT_SYMBOL_GPL(vfs_listxattr);
 
 int
-vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name)
+vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
+		struct file *file)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
@@ -177,7 +178,7 @@ vfs_removexattr(struct dentry *dentry, s
 	if (error)
 		return error;
 
-	error = security_inode_removexattr(dentry, mnt, name);
+	error = security_inode_removexattr(dentry, mnt, name, file);
 	if (error)
 		return error;
 
@@ -197,7 +198,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
  */
 static long
 setxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
-	 void __user *value, size_t size, int flags)
+	 void __user *value, size_t size, int flags, struct file *file)
 {
 	int error;
 	void *kvalue = NULL;
@@ -224,7 +225,7 @@ setxattr(struct dentry *dentry, struct v
 		}
 	}
 
-	error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags);
+	error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags, file);
 	kfree(kvalue);
 	return error;
 }
@@ -239,7 +240,7 @@ sys_setxattr(char __user *path, char __u
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = setxattr(nd.dentry, nd.mnt, name, value, size, flags);
+	error = setxattr(nd.dentry, nd.mnt, name, value, size, flags, NULL);
 	path_release(&nd);
 	return error;
 }
@@ -254,7 +255,7 @@ sys_lsetxattr(char __user *path, char __
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = setxattr(nd.dentry, nd.mnt, name, value, size, flags);
+	error = setxattr(nd.dentry, nd.mnt, name, value, size, flags, NULL);
 	path_release(&nd);
 	return error;
 }
@@ -272,7 +273,7 @@ sys_fsetxattr(int fd, char __user *name,
 		return error;
 	dentry = f->f_path.dentry;
 	audit_inode(NULL, dentry->d_inode);
-	error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags);
+	error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags, f);
 	fput(f);
 	return error;
 }
@@ -282,7 +283,7 @@ sys_fsetxattr(int fd, char __user *name,
  */
 static ssize_t
 getxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
-	 void __user *value, size_t size)
+	 void __user *value, size_t size, struct file *file)
 {
 	ssize_t error;
 	void *kvalue = NULL;
@@ -302,7 +303,7 @@ getxattr(struct dentry *dentry, struct v
 			return -ENOMEM;
 	}
 
-	error = vfs_getxattr(dentry, mnt, kname, kvalue, size);
+	error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
 	if (error > 0) {
 		if (size && copy_to_user(value, kvalue, error))
 			error = -EFAULT;
@@ -325,7 +326,7 @@ sys_getxattr(char __user *path, char __u
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = getxattr(nd.dentry, nd.mnt, name, value, size);
+	error = getxattr(nd.dentry, nd.mnt, name, value, size, NULL);
 	path_release(&nd);
 	return error;
 }
@@ -340,7 +341,7 @@ sys_lgetxattr(char __user *path, char __
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = getxattr(nd.dentry, nd.mnt, name, value, size);
+	error = getxattr(nd.dentry, nd.mnt, name, value, size, NULL);
 	path_release(&nd);
 	return error;
 }
@@ -355,7 +356,7 @@ sys_fgetxattr(int fd, char __user *name,
 	if (!f)
 		return error;
 	audit_inode(NULL, f->f_path.dentry->d_inode);
-	error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
+	error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
 	fput(f);
 	return error;
 }
@@ -365,7 +366,7 @@ sys_fgetxattr(int fd, char __user *name,
  */
 static ssize_t
 listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
-	  size_t size)
+	  size_t size, struct file *file)
 {
 	ssize_t error;
 	char *klist = NULL;
@@ -378,7 +379,7 @@ listxattr(struct dentry *dentry, struct 
 			return -ENOMEM;
 	}
 
-	error = vfs_listxattr(dentry, mnt, klist, size);
+	error = vfs_listxattr(dentry, mnt, klist, size, file);
 	if (error > 0) {
 		if (size && copy_to_user(list, klist, error))
 			error = -EFAULT;
@@ -400,7 +401,7 @@ sys_listxattr(char __user *path, char __
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = listxattr(nd.dentry, nd.mnt, list, size);
+	error = listxattr(nd.dentry, nd.mnt, list, size, NULL);
 	path_release(&nd);
 	return error;
 }
@@ -414,7 +415,7 @@ sys_llistxattr(char __user *path, char _
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = listxattr(nd.dentry, nd.mnt, list, size);
+	error = listxattr(nd.dentry, nd.mnt, list, size, NULL);
 	path_release(&nd);
 	return error;
 }
@@ -429,7 +430,7 @@ sys_flistxattr(int fd, char __user *list
 	if (!f)
 		return error;
 	audit_inode(NULL, f->f_path.dentry->d_inode);
-	error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
+	error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
 	fput(f);
 	return error;
 }
@@ -438,7 +439,8 @@ sys_flistxattr(int fd, char __user *list
  * Extended attribute REMOVE operations
  */
 static long
-removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name)
+removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
+	    struct file *file)
 {
 	int error;
 	char kname[XATTR_NAME_MAX + 1];
@@ -449,7 +451,7 @@ removexattr(struct dentry *dentry, struc
 	if (error < 0)
 		return error;
 
-	return vfs_removexattr(dentry, mnt, kname);
+	return vfs_removexattr(dentry, mnt, kname, file);
 }
 
 asmlinkage long
@@ -461,7 +463,7 @@ sys_removexattr(char __user *path, char 
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = removexattr(nd.dentry, nd.mnt, name);
+	error = removexattr(nd.dentry, nd.mnt, name, NULL);
 	path_release(&nd);
 	return error;
 }
@@ -475,7 +477,7 @@ sys_lremovexattr(char __user *path, char
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = removexattr(nd.dentry, nd.mnt, name);
+	error = removexattr(nd.dentry, nd.mnt, name, NULL);
 	path_release(&nd);
 	return error;
 }
@@ -492,7 +494,7 @@ sys_fremovexattr(int fd, char __user *na
 		return error;
 	dentry = f->f_path.dentry;
 	audit_inode(NULL, dentry->d_inode);
-	error = removexattr(dentry, f->f_path.mnt, name);
+	error = removexattr(dentry, f->f_path.mnt, name, f);
 	fput(f);
 	return error;
 }
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -49,8 +49,8 @@ extern void cap_capset_set (struct task_
 extern int cap_bprm_set_security (struct linux_binprm *bprm);
 extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
 extern int cap_bprm_secureexec(struct linux_binprm *bprm);
-extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name);
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags, struct file *file);
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name, struct file *file);
 extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
 extern void cap_task_reparent_to_init (struct task_struct *p);
 extern int cap_syslog (int type);
@@ -1243,16 +1243,18 @@ struct security_operations {
 	int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
         void (*inode_delete) (struct inode *inode);
 	int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
-			       char *name, void *value, size_t size, int flags);
+			       char *name, void *value, size_t size, int flags,
+			       struct file *file);
 	void (*inode_post_setxattr) (struct dentry *dentry,
 				     struct vfsmount *mnt,
 				     char *name, void *value,
 				     size_t size, int flags);
 	int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
-			       char *name);
-	int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
+			       char *name, struct file *file);
+	int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
+				struct file *file);
 	int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
-				  char *name);
+				  char *name, struct file *file);
 	const char *(*inode_xattr_getsuffix) (void);
   	int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
   	int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
@@ -1766,12 +1768,13 @@ static inline void security_inode_delete
 
 static inline int security_inode_setxattr (struct dentry *dentry,
 					   struct vfsmount *mnt, char *name,
-					   void *value, size_t size, int flags)
+					   void *value, size_t size, int flags,
+					   struct file *file)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
 	return security_ops->inode_setxattr (dentry, mnt, name, value, size,
-					     flags);
+					     flags, file);
 }
 
 static inline void security_inode_post_setxattr (struct dentry *dentry,
@@ -1781,31 +1784,35 @@ static inline void security_inode_post_s
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return;
-	security_ops->inode_post_setxattr (dentry, mnt, name, value, size, flags);
+	security_ops->inode_post_setxattr (dentry, mnt, name, value, size,
+					   flags);
 }
 
 static inline int security_inode_getxattr (struct dentry *dentry,
-					    struct vfsmount *mnt, char *name)
+					   struct vfsmount *mnt, char *name,
+					   struct file *file)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_getxattr (dentry, mnt, name);
+	return security_ops->inode_getxattr (dentry, mnt, name, file);
 }
 
 static inline int security_inode_listxattr (struct dentry *dentry,
-					    struct vfsmount *mnt)
+					    struct vfsmount *mnt,
+					    struct file *file)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_listxattr (dentry, mnt);
+	return security_ops->inode_listxattr (dentry, mnt, file);
 }
 
 static inline int security_inode_removexattr (struct dentry *dentry,
-					      struct vfsmount *mnt, char *name)
+					      struct vfsmount *mnt, char *name,
+					      struct file *file)
 {
 	if (unlikely (IS_PRIVATE (dentry->d_inode)))
 		return 0;
-	return security_ops->inode_removexattr (dentry, mnt, name);
+	return security_ops->inode_removexattr (dentry, mnt, name, file);
 }
 
 static inline const char *security_inode_xattr_getsuffix(void)
@@ -2480,9 +2487,10 @@ static inline void security_inode_delete
 
 static inline int security_inode_setxattr (struct dentry *dentry,
 					   struct vfsmount *mnt, char *name,
-					   void *value, size_t size, int flags)
+					   void *value, size_t size, int flags,
+					   struct file *file)
 {
-	return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
+	return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
 }
 
 static inline void security_inode_post_setxattr (struct dentry *dentry,
@@ -2493,21 +2501,24 @@ static inline void security_inode_post_s
 { }
 
 static inline int security_inode_getxattr (struct dentry *dentry,
-					    struct vfsmount *mnt, char *name)
+					    struct vfsmount *mnt, char *name,
+					    struct file *file)
 {
 	return 0;
 }
 
 static inline int security_inode_listxattr (struct dentry *dentry,
-					    struct vfsmount *mnt)
+					    struct vfsmount *mnt,
+					    struct file *file)
 {
 	return 0;
 }
 
 static inline int security_inode_removexattr (struct dentry *dentry,
-					      struct vfsmount *mnt, char *name)
+					      struct vfsmount *mnt, char *name,
+					      struct file *file)
 {
-	return cap_inode_removexattr(dentry, mnt, name);
+	return cap_inode_removexattr(dentry, mnt, name, file);
 }
 
 static inline const char *security_inode_xattr_getsuffix (void)
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -47,12 +47,12 @@ struct xattr_handler {
 };
 
 ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
-		     size_t);
+		     size_t, struct file *);
 ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list,
-		      size_t size);
+		      size_t size, struct file *);
 int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
-		 int);
-int vfs_removexattr(struct dentry *, struct vfsmount *, char *);
+		 int, struct file *);
+int vfs_removexattr(struct dentry *, struct vfsmount *, char *, struct file *);
 
 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -191,7 +191,7 @@ int cap_bprm_secureexec (struct linux_bi
 }
 
 int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
-		       void *value, size_t size, int flags)
+		       void *value, size_t size, int flags, struct file *file)
 {
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 		     sizeof(XATTR_SECURITY_PREFIX) - 1)  &&
@@ -201,7 +201,7 @@ int cap_inode_setxattr(struct dentry *de
 }
 
 int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
-			  char *name)
+			  char *name, struct file *file)
 {
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 		     sizeof(XATTR_SECURITY_PREFIX) - 1)  &&
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -352,7 +352,7 @@ static void dummy_inode_delete (struct i
 
 static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
 				 char *name, void *value, size_t size,
-				 int flags)
+				 int flags, struct file *file)
 {
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 		     sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -369,18 +369,20 @@ static void dummy_inode_post_setxattr (s
 }
 
 static int dummy_inode_getxattr (struct dentry *dentry,
-			          struct vfsmount *mnt, char *name)
+			          struct vfsmount *mnt, char *name,
+				  struct file *file)
 {
 	return 0;
 }
 
-static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
+static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
+				  struct file *file)
 {
 	return 0;
 }
 
 static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
-				    char *name)
+				    char *name, struct file *file)
 {
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 		     sizeof(XATTR_SECURITY_PREFIX) - 1) &&
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2307,7 +2307,7 @@ static int selinux_inode_getattr(struct 
 
 static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
 				  char *name, void *value, size_t size,
-				  int flags)
+				  int flags, struct file *file)
 {
 	struct task_security_struct *tsec = current->security;
 	struct inode *inode = dentry->d_inode;
@@ -2394,18 +2394,20 @@ static void selinux_inode_post_setxattr(
 }
 
 static int selinux_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt,
-				   char *name)
+				   char *name, struct file *file)
 {
 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
 
-static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
+static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
+				    struct file *file)
 {
 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
 
 static int selinux_inode_removexattr (struct dentry *dentry,
-				      struct vfsmount *mnt, char *name)
+				      struct vfsmount *mnt, char *name,
+				      struct file *file)
 {
 	if (strcmp(name, XATTR_NAME_SELINUX)) {
 		if (!strncmp(name, XATTR_SECURITY_PREFIX,

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 34/45] Factor out sysctl pathname code
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (32 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 33/45] Pass struct file down the inode_*xattr security LSM hooks jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 35/45] Allow permission functions to tell between parent and leaf checks jjohansen
                   ` (11 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher, John Johansen

[-- Attachment #1: sysctl-pathname.diff --]
[-- Type: text/plain, Size: 2803 bytes --]

Convert the selinux sysctl pathname computation code into a standalone
function.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 include/linux/sysctl.h   |    2 ++
 kernel/sysctl.c          |   27 +++++++++++++++++++++++++++
 security/selinux/hooks.c |   35 +++++------------------------------
 3 files changed, 34 insertions(+), 30 deletions(-)

--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -963,6 +963,8 @@ extern int proc_doulongvec_minmax(ctl_ta
 extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int,
 				      struct file *, void __user *, size_t *, loff_t *);
 
+extern char *sysctl_pathname(ctl_table *, char *, int);
+
 extern int do_sysctl (int __user *name, int nlen,
 		      void __user *oldval, size_t __user *oldlenp,
 		      void __user *newval, size_t newlen);
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1110,6 +1110,33 @@ struct ctl_table_header *sysctl_head_nex
 	return NULL;
 }
 
+char *sysctl_pathname(ctl_table *table, char *buffer, int buflen)
+{
+	if (buflen < 1)
+		return NULL;
+	buffer += --buflen;
+	*buffer = '\0';
+
+	while (table) {
+		int namelen = strlen(table->procname);
+
+		if (buflen < namelen + 1)
+			return NULL;
+		buflen -= namelen + 1;
+		buffer -= namelen;
+		memcpy(buffer, table->procname, namelen);
+		*--buffer = '/';
+		table = table->parent;
+	}
+	if (buflen < 4)
+		return NULL;
+	buffer -= 4;
+	memcpy(buffer, "/sys", 4);
+
+	return buffer;
+}
+EXPORT_SYMBOL(sysctl_pathname);
+
 #ifdef CONFIG_SYSCTL_SYSCALL
 int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
 	       void __user *newval, size_t newlen)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1427,40 +1427,15 @@ static int selinux_capable(struct task_s
 
 static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
 {
-	int buflen, rc;
-	char *buffer, *path, *end;
+	char *buffer, *path;
+	int rc = -ENOMEM;
 
-	rc = -ENOMEM;
 	buffer = (char*)__get_free_page(GFP_KERNEL);
 	if (!buffer)
 		goto out;
-
-	buflen = PAGE_SIZE;
-	end = buffer+buflen;
-	*--end = '\0';
-	buflen--;
-	path = end-1;
-	*path = '/';
-	while (table) {
-		const char *name = table->procname;
-		size_t namelen = strlen(name);
-		buflen -= namelen + 1;
-		if (buflen < 0)
-			goto out_free;
-		end -= namelen;
-		memcpy(end, name, namelen);
-		*--end = '/';
-		path = end;
-		table = table->parent;
-	}
-	buflen -= 4;
-	if (buflen < 0)
-		goto out_free;
-	end -= 4;
-	memcpy(end, "/sys", 4);
-	path = end;
-	rc = security_genfs_sid("proc", path, tclass, sid);
-out_free:
+	path = sysctl_pathname(table, buffer, PAGE_SIZE);
+	if (path)
+		rc = security_genfs_sid("proc", path, tclass, sid);
 	free_page((unsigned long)buffer);
 out:
 	return rc;

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 35/45] Allow permission functions to tell between parent and leaf checks
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (33 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 34/45] Factor out sysctl pathname code jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-15  9:08   ` Pavel Machek
  2007-05-14 11:06 ` [AppArmor 36/45] Export audit subsystem for use by modules jjohansen
                   ` (10 subsequent siblings)
  45 siblings, 1 reply; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher

[-- Attachment #1: parent-permission.diff --]
[-- Type: text/plain, Size: 832 bytes --]

Set the LOOKUP_CONTINUE flag when checking parent permissions. This allows
permission functions to tell between parent and leaf checks.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 fs/namei.c |    6 ++++++
 1 file changed, 6 insertions(+)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1409,6 +1409,10 @@ static int may_delete(struct inode *dir,
 	BUG_ON(victim->d_parent->d_inode != dir);
 	audit_inode_child(victim->d_name.name, victim->d_inode, dir);
 
+#if 0
+	if (nd)
+		nd->flags |= LOOKUP_CONTINUE;
+#endif
 	error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
 	if (error)
 		return error;
@@ -1446,6 +1450,8 @@ static inline int may_create(struct inod
 		return -EEXIST;
 	if (IS_DEADDIR(dir))
 		return -ENOENT;
+	if (nd)
+		nd->flags |= LOOKUP_CONTINUE;
 	return permission(dir,MAY_WRITE | MAY_EXEC, nd);
 }
 

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 36/45] Export audit subsystem for use by modules
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (34 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 35/45] Allow permission functions to tell between parent and leaf checks jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 37/45] AppArmor: Main Part jjohansen
                   ` (9 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher, John Johansen

[-- Attachment #1: apparmor-audit.diff --]
[-- Type: text/plain, Size: 2056 bytes --]

Adds necessary export symbols for audit subsystem routines.
Changes audit_log_vformat to be externally visible (analagous to vprintf)
Patch is not in mainline -- pending AppArmor code submission to lkml

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>

---
 include/linux/audit.h |    5 +++++
 kernel/audit.c        |    6 ++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -114,6 +114,8 @@
 #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
 #define AUDIT_ANOM_ABEND            1701 /* Process ended abnormally */
 
+#define AUDIT_APPARMOR		1500	/* AppArmor audit */
+
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
 /* Rule flags */
@@ -499,6 +501,9 @@ extern void		    audit_log(struct audit_
 				      __attribute__((format(printf,4,5)));
 
 extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
+extern void		    audit_log_vformat(struct audit_buffer *ab,
+					      const char *fmt, va_list args)
+			    __attribute__((format(printf,2,0)));
 extern void		    audit_log_format(struct audit_buffer *ab,
 					     const char *fmt, ...)
 			    __attribute__((format(printf,2,3)));
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1054,8 +1054,7 @@ static inline int audit_expand(struct au
  * will be called a second time.  Currently, we assume that a printk
  * can't format message larger than 1024 bytes, so we don't either.
  */
-static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
-			      va_list args)
+void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
 {
 	int len, avail;
 	struct sk_buff *skb;
@@ -1311,3 +1310,6 @@ EXPORT_SYMBOL(audit_log_start);
 EXPORT_SYMBOL(audit_log_end);
 EXPORT_SYMBOL(audit_log_format);
 EXPORT_SYMBOL(audit_log);
+EXPORT_SYMBOL_GPL(audit_log_vformat);
+EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
+EXPORT_SYMBOL_GPL(audit_log_d_path);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 37/45] AppArmor: Main Part
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (35 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 36/45] Export audit subsystem for use by modules jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-15  9:12   ` Pavel Machek
  2007-05-14 11:06 ` [AppArmor 38/45] AppArmor: Module and LSM hooks jjohansen
                   ` (8 subsequent siblings)
  45 siblings, 1 reply; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, John Johansen, Andreas Gruenbacher

[-- Attachment #1: apparmor-main.diff --]
[-- Type: text/plain, Size: 38356 bytes --]

The underlying functions by which the AppArmor LSM hooks are implemented.

Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

Index: b/security/apparmor/main.c
===================================================================
--- /dev/null
+++ b/security/apparmor/main.c
@@ -0,0 +1,1399 @@
+/*
+ *	Copyright (C) 2002-2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor Core
+ */
+
+#include <linux/security.h>
+#include <linux/namei.h>
+#include <linux/audit.h>
+#include <linux/mount.h>
+#include <linux/ptrace.h>
+
+#include "apparmor.h"
+
+#include "inline.h"
+
+/*
+ * Table of capability names: we generate it from capabilities.h.
+ */
+static const char *capability_names[] = {
+#include "capability_names.h"
+};
+
+/* NULL complain profile
+ *
+ * Used when in complain mode, to emit Permitting messages for non-existant
+ * profiles and hats.  This is necessary because of selective mode, in which
+ * case we need a complain null_profile and enforce null_profile
+ *
+ * The null_complain_profile cannot be statically allocated, because it
+ * can be associated to files which keep their reference even if apparmor is
+ * unloaded
+ */
+struct aa_profile *null_complain_profile;
+
+static inline void aa_permerror2result(int perm_result, struct aa_audit *sa)
+{
+	if (perm_result == 0) {	/* success */
+		sa->result = 1;
+		sa->error_code = 0;
+	} else { /* -ve internal error code or +ve mask of denied perms */
+		sa->result = 0;
+		sa->error_code = perm_result;
+	}
+}
+
+/**
+ * aa_file_denied - check for @mask access on a file
+ * @profile: profile to check against
+ * @name: pathname of file
+ * @mask: permission mask requested for file
+ *
+ * Return %0 on success, or else the permissions in @mask that the
+ * profile denies.
+ */
+static int aa_file_denied(struct aa_profile *profile, const char *name,
+			  int mask)
+{
+	return (mask & ~aa_match(profile->file_rules, name));
+}
+
+/**
+ * aa_link_denied - check for permission to link a file
+ * @profile: profile to check against
+ * @link: pathname of link being created
+ * @target: pathname of target to be linked to
+ *
+ * Return %0 on success, or else the permissions that the profile denies.
+ */
+static int aa_link_denied(struct aa_profile *profile, const char *link,
+			  const char *target)
+{
+	int l_mode, t_mode;
+
+	l_mode = aa_match(profile->file_rules, link);
+	t_mode = aa_match(profile->file_rules, target);
+
+	/* Link always requires 'l' on the link, a subset of the
+	 * target's 'r', 'w', 'x', and 'm' permissions on the link, and
+	 * if the link has 'x', an exact match of all the execute flags
+	 * ('i', 'u', 'U', 'p', 'P').
+	 */
+#define RWXM (MAY_READ | MAY_WRITE | MAY_EXEC | AA_EXEC_MMAP)
+	if ((l_mode & AA_MAY_LINK) &&
+	    (l_mode & RWXM) && !(l_mode & ~t_mode & RWXM) &&
+	    (!(l_mode & MAY_EXEC) ||
+	     ((l_mode & AA_EXEC_MODIFIERS) == (t_mode & AA_EXEC_MODIFIERS) &&
+	      (l_mode & AA_EXEC_UNSAFE) == (t_mode & AA_EXEC_UNSAFE))))
+		return 0;
+#undef RWXM
+	/* FIXME: There currenly is no way to report which permissions
+	 * we expect in t_mode, so linking could fail even after learning
+	 * the required l_mode.
+	 */
+	return AA_MAY_LINK;
+}
+
+/**
+ * mangle -- escape special characters in str
+ * @str: string to escape
+ * @buffer: buffer containing str
+ *
+ * Escape special characters in @str, which is contained in @buffer. @str must
+ * be aligned to the end of the buffer, and the space between @buffer and @str
+ * may be used for escaping.
+ *
+ * Returns @str if no escaping was necessary, a pointer to the beginning of the
+ * escaped string, or NULL if there was not enough space in @buffer.  When
+ * called with a NULL buffer, the return value tells whether any escaping is
+ * necessary.
+ */
+static const char *mangle(const char *str, char *buffer)
+{
+	static const char c_escape[] = {
+		['\a'] = 'a',	['\b'] = 'b',
+		['\f'] = 'f',	['\n'] = 'n',
+		['\r'] = 'r',	['\t'] = 't',
+		['\v'] = 'v',
+		[' '] = ' ',	['\\'] = '\\',
+	};
+	const char *s;
+	char *t, c;
+
+#define mangle_escape(c)						\
+	unlikely((unsigned char)(c) < ARRAY_SIZE(c_escape) &&		\
+		 c_escape[(unsigned char)c])
+
+	for (s = (char *)str; (c = *s) != '\0'; s++)
+		if (mangle_escape(c))
+			goto escape;
+	return str;
+
+escape:
+	if (!buffer)
+		return NULL;
+	for (s = str, t = buffer; (c = *s) != '\0'; s++) {
+		if (mangle_escape(c)) {
+			if (t == s)
+				return NULL;
+			*t++ = '\\';
+			*t++ = c_escape[(unsigned char)c];
+		} else
+			*t++ = c;
+	}
+	*t++ = '\0';
+
+#undef mangle_escape
+
+	return buffer;
+}
+
+/**
+ * aa_get_name - compute the pathname of a file
+ * @dentry: dentry of the file
+ * @mnt: vfsmount of the file
+ * @buffer: buffer that aa_get_name() allocated
+ * @check: AA_CHECK_DIR is set if the file is a directory
+ *
+ * Returns a pointer to the beginning of the pathname (which usually differs
+ * from the beginning of the buffer), or an error code.
+ *
+ * We need @check to indicate whether the file is a directory or not because
+ * the file may not yet exist, and so we cannot check the inode's file type.
+ */
+static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
+			 char **buffer, int check)
+{
+	char *name;
+	int is_dir, size = 256;
+
+	is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
+
+	for (;;) {
+		char *buf = kmalloc(size, GFP_KERNEL);
+		if (!buf)
+			return ERR_PTR(-ENOMEM);
+
+		name = d_namespace_path(dentry, mnt, buf, size - is_dir);
+
+		/* Make sure we have enough space for name mangling. */
+		if (!IS_ERR(name) &&
+		    (check & AA_CHECK_MANGLE) && name - buf <= size / 2)
+			name = ERR_PTR(-ENAMETOOLONG);
+
+		if (!IS_ERR(name)) {
+			if (name[0] != '/') {
+				/*
+				 * This dentry is not connected to the
+				 * namespace root -- reject access.
+				 */
+				kfree(buf);
+				return ERR_PTR(-ENOENT);
+			}
+			if (is_dir && name[1] != '\0') {
+				/*
+				 * Append "/" to the pathname. The root
+				 * directory is a special case; it already
+				 * ends in slash.
+				 */
+				buf[size - 2] = '/';
+				buf[size - 1] = '\0';
+			}
+
+			*buffer = buf;
+			return name;
+		}
+		if (PTR_ERR(name) != -ENAMETOOLONG)
+			return name;
+
+		kfree(buf);
+		size <<= 1;
+		if (size > apparmor_path_max)
+			return ERR_PTR(-ENAMETOOLONG);
+	}
+}
+
+static inline void aa_put_name_buffer(char *buffer)
+{
+	kfree(buffer);
+}
+
+/**
+ * aa_perm_dentry - check if @profile allows @mask for a file
+ * @profile: profile to check against
+ * @dentry: dentry of the file
+ * @mnt: vfsmount o the file
+ * @sa: audit context
+ * @mask: requested profile permissions
+ * @check: kind of check to perform
+ *
+ * Returns 0 upon success, or else an error code.
+ *
+ * @check indicates the file type, and whether the file was accessed through
+ * an open file descriptor (AA_CHECK_FD) or not.
+ */
+static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
+			  struct vfsmount *mnt, struct aa_audit *sa, int mask,
+			  int check)
+{
+	int denied_mask, error;
+
+again:
+	sa->buffer = NULL;
+	sa->name = aa_get_name(dentry, mnt, &sa->buffer, check);
+
+	if (IS_ERR(sa->name)) {
+		/*
+		 * deleted files are given a pass on permission checks when
+		 * accessed through a file descriptor.
+		 */
+		if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
+			denied_mask = 0;
+		else
+			denied_mask = PTR_ERR(sa->name);
+		sa->name = NULL;
+	} else
+		denied_mask = aa_file_denied(profile, sa->name, mask);
+
+	aa_permerror2result(denied_mask, sa);
+
+	error = aa_audit(profile, sa);
+
+	aa_put_name_buffer(sa->buffer);
+	if (error == -ENAMETOOLONG) {
+		BUG_ON(check & AA_CHECK_MANGLE);
+		check |= AA_CHECK_MANGLE;
+		goto again;
+	}
+
+	return error;
+}
+
+/**
+ * attach_nullprofile - allocate and attach a null_profile hat to profile
+ * @profile: profile to attach a null_profile hat to.
+ *
+ * Return %0 (success) or error (-%ENOMEM)
+ */
+int attach_nullprofile(struct aa_profile *profile)
+{
+	struct aa_profile *hat = NULL;
+	char *hatname = NULL;
+
+	hat = alloc_aa_profile();
+	if (!hat)
+		goto fail;
+	if (profile->flags.complain)
+		hatname = kstrdup("null-complain-profile", GFP_KERNEL);
+	else
+		hatname = kstrdup("null-profile", GFP_KERNEL);
+	if (!hatname)
+		goto fail;
+
+	hat->flags.complain = profile->flags.complain;
+	hat->name = hatname;
+	hat->parent = profile;
+
+	profile->null_profile = hat;
+
+	return 0;
+
+fail:
+	kfree(hatname);
+	free_aa_profile(hat);
+
+	return -ENOMEM;
+}
+
+/**
+ * alloc_null_complain_profile - Allocate the global null_complain_profile.
+ *
+ * Return %0 (success) or error (-%ENOMEM)
+ */
+int alloc_null_complain_profile(void)
+{
+	null_complain_profile = alloc_aa_profile();
+	if (!null_complain_profile)
+		goto fail;
+
+	null_complain_profile->name =
+		kstrdup("null-complain-profile", GFP_KERNEL);
+
+	if (!null_complain_profile->name)
+		goto fail;
+
+	null_complain_profile->flags.complain = 1;
+	if (attach_nullprofile(null_complain_profile))
+		goto fail;
+
+	return 0;
+
+fail:
+	/* free_aa_profile is safe for freeing partially constructed objects */
+	free_aa_profile(null_complain_profile);
+	null_complain_profile = NULL;
+
+	return -ENOMEM;
+}
+
+/**
+ * free_null_complain_profile - Free null profiles
+ */
+void free_null_complain_profile(void)
+{
+	aa_put_profile(null_complain_profile);
+	null_complain_profile = NULL;
+}
+
+/**
+ * aa_audit_message - Log a message to the audit subsystem
+ * @profile: profile to check against
+ * @gfp: allocation flags
+ * @flags: audit flags
+ * @fmt: varargs fmt
+ */
+int aa_audit_message(struct aa_profile *profile, gfp_t gfp, const char *fmt,
+		     ...)
+{
+	int ret;
+	struct aa_audit sa;
+
+	sa.type = AA_AUDITTYPE_MSG;
+	sa.name = fmt;
+	va_start(sa.vaval, fmt);
+	sa.flags = 0;
+	sa.gfp_mask = gfp;
+	sa.error_code = 0;
+	sa.result = 0;	/* fake failure: force message to be logged */
+
+	ret = aa_audit(profile, &sa);
+
+	va_end(sa.vaval);
+
+	return ret;
+}
+
+/**
+ * aa_audit_syscallreject - Log a syscall rejection to the audit subsystem
+ * @profile: profile to check against
+ * @msg: string describing syscall being rejected
+ * @gfp: memory allocation flags
+ */
+int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
+			   const char *msg)
+{
+	struct aa_audit sa;
+
+	sa.type = AA_AUDITTYPE_SYSCALL;
+	sa.name = msg;
+	sa.flags = 0;
+	sa.gfp_mask = gfp;
+	sa.error_code = 0;
+	sa.result = 0; /* failure */
+
+	return aa_audit(profile, &sa);
+}
+
+/**
+ * aa_audit - Log an audit event to the audit subsystem
+ * @profile: profile to check against
+ * @sa: audit event
+ */
+int aa_audit(struct aa_profile *profile, struct aa_audit *sa)
+{
+	struct audit_buffer *ab = NULL;
+	struct audit_context *audit_cxt;
+
+	const char *logcls;
+	unsigned int flags;
+	int audit = 0,
+	    complain = 0,
+	    error = -EINVAL,
+	    opspec_error = -EACCES;
+
+	const gfp_t gfp_mask = sa->gfp_mask;
+
+	/*
+	 * sa->result:	  1 success, 0 failure
+	 * sa->error_code: success: 0
+	 *		  failure: +ve mask of failed permissions or -ve
+	 *		  system error
+	 */
+
+	if (likely(sa->result)) {
+		if (likely(!PROFILE_AUDIT(profile))) {
+			/* nothing to log */
+			error = 0;
+			goto out;
+		} else {
+			audit = 1;
+			logcls = "AUDITING";
+		}
+	} else if (sa->error_code < 0) {
+		audit_log(current->audit_context, gfp_mask, AUDIT_APPARMOR,
+			"Internal error auditing event type %d (error %d)",
+			sa->type, sa->error_code);
+		AA_ERROR("Internal error auditing event type %d (error %d)\n",
+			sa->type, sa->error_code);
+		error = sa->error_code;
+		goto out;
+	} else if (sa->type == AA_AUDITTYPE_SYSCALL) {
+		/* Currently AA_AUDITTYPE_SYSCALL is for rejects only.
+		 * Values set by aa_audit_syscallreject will get us here.
+		 */
+		logcls = "REJECTING";
+	} else {
+		complain = PROFILE_COMPLAIN(profile);
+		logcls = complain ? "PERMITTING" : "REJECTING";
+	}
+
+	/* In future extend w/ per-profile flags
+	 * (flags |= sa->profile->flags)
+	 */
+	flags = sa->flags;
+	if (apparmor_logsyscall)
+		flags |= AA_AUDITFLAG_AUDITSS_SYSCALL;
+
+
+	/* Force full audit syscall logging regardless of global setting if
+	 * we are rejecting a syscall
+	 */
+	if (sa->type == AA_AUDITTYPE_SYSCALL) {
+		audit_cxt = current->audit_context;
+	} else {
+		audit_cxt = (flags & AA_AUDITFLAG_AUDITSS_SYSCALL) ?
+			current->audit_context : NULL;
+	}
+
+	ab = audit_log_start(audit_cxt, gfp_mask, AUDIT_APPARMOR);
+
+	if (!ab) {
+		AA_ERROR("Unable to log event (%d) to audit subsys\n",
+			sa->type);
+		if (complain)
+			error = 0;
+		goto out;
+	}
+
+	/* messages get special handling */
+	if (sa->type == AA_AUDITTYPE_MSG) {
+		audit_log_vformat(ab, sa->name, sa->vaval);
+		audit_log_end(ab);
+		error = 0;
+		goto out;
+	}
+
+	if (sa->type & AA_MANGLE_NAME) {
+		sa->name = mangle(sa->name, sa->buffer);
+		if (!sa->name)
+			return -ENAMETOOLONG;
+	}
+	if (sa->type & AA_MANGLE_NAME2) {
+		sa->name2 = mangle(sa->name2, sa->buffer2);
+		if (!sa->name2)
+			return -ENAMETOOLONG;
+
+	}
+
+	/* log operation */
+
+	audit_log_format(ab, "%s ", logcls);	/* REJECTING/ALLOWING/etc */
+
+#define NOFLAGS(x) ((x) & ~(AA_MANGLE_NAME | AA_MANGLE_NAME2))
+
+	switch(NOFLAGS(sa->type)) {
+	case NOFLAGS(AA_AUDITTYPE_FILE): {
+		int perm = audit ? sa->mask : sa->error_code;
+
+		audit_log_format(ab, "%s%s%s%s%s access to %s ",
+				 perm & AA_EXEC_MMAP ? "m" : "",
+				 perm & MAY_READ  ? "r" : "",
+				 perm & MAY_WRITE ? "w" : "",
+				 perm & MAY_EXEC  ? "x" : "",
+				 perm & AA_MAY_LINK  ? "l" : "",
+				 sa->name);
+		opspec_error = -EPERM;
+		break;
+	}
+	case NOFLAGS(AA_AUDITTYPE_DIR):
+		audit_log_format(ab, "%s on %s ", sa->name2, sa->name);
+		break;
+	case NOFLAGS(AA_AUDITTYPE_ATTR): {
+		struct iattr *iattr = sa->iattr;
+
+		audit_log_format(ab,
+			"attribute (%s%s%s%s%s%s%s) change to %s ",
+			iattr->ia_valid & ATTR_MODE ? "mode," : "",
+			iattr->ia_valid & ATTR_UID ? "uid," : "",
+			iattr->ia_valid & ATTR_GID ? "gid," : "",
+			iattr->ia_valid & ATTR_SIZE ? "size," : "",
+			((iattr->ia_valid & ATTR_ATIME_SET) ||
+			 (iattr->ia_valid & ATTR_ATIME)) ? "atime," : "",
+			((iattr->ia_valid & ATTR_MTIME_SET) ||
+			 (iattr->ia_valid & ATTR_MTIME)) ? "mtime," : "",
+			iattr->ia_valid & ATTR_CTIME ? "ctime," : "",
+			sa->name);
+		break;
+	}
+	case NOFLAGS(AA_AUDITTYPE_XATTR):
+		audit_log_format(ab, "%s on %s ", sa->name2, sa->name);
+		break;
+	case NOFLAGS(AA_AUDITTYPE_LINK):
+		audit_log_format(ab, "link access from %s to %s ", sa->name,
+				 sa->name2);
+		break;
+	case NOFLAGS(AA_AUDITTYPE_CAP):
+		audit_log_format(ab, "access to capability '%s' ",
+			capability_names[sa->capability]);
+		opspec_error = -EPERM;
+		break;
+	case NOFLAGS(AA_AUDITTYPE_SYSCALL):
+		audit_log_format(ab, "access to syscall '%s' ", sa->name);
+		opspec_error = -EPERM;
+		break;
+	default:
+		WARN_ON(1);
+		return error;
+	}
+
+#undef NOFLAGS
+
+	audit_log_format(ab, "(%d profile %s active %s)",
+			 current->pid, profile->parent->name, profile->name);
+
+	audit_log_end(ab);
+
+	if (complain)
+		error = 0;
+	else
+		error = sa->result ? 0 : opspec_error;
+out:
+	return error;
+}
+
+/**
+ * aa_attr - check if attribute change is allowed
+ * @profile: profile to check against
+ * @dentry: dentry of the file to check
+ * @mnt: vfsmount of the file to check
+ * @iattr: attribute changes requested
+ */
+int aa_attr(struct aa_profile *profile, struct dentry *dentry,
+	    struct vfsmount *mnt, struct iattr *iattr)
+{
+	struct inode *inode = dentry->d_inode;
+	int error, check;
+	struct aa_audit sa;
+
+	sa.type = AA_AUDITTYPE_ATTR;
+	sa.iattr = iattr;
+	sa.flags = 0;
+	sa.gfp_mask = GFP_KERNEL;
+
+	check = 0;
+	if (inode && S_ISDIR(inode->i_mode))
+		check |= AA_CHECK_DIR;
+	if (iattr->ia_valid & ATTR_FILE)
+		check |= AA_CHECK_FD;
+
+	error = aa_perm_dentry(profile, dentry, mnt, &sa, MAY_WRITE, check);
+
+	return error;
+}
+
+/**
+ * aa_perm_xattr - check if xattr attribute change is allowed
+ * @profile: profile to check against
+ * @dentry: dentry of the file to check
+ * @mnt: vfsmount of the file to check
+ * @operation: xattr operation being done
+ * @mask: access mode requested
+ * @check: kind of check to perform
+ */
+int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
+		  struct vfsmount *mnt, const char *operation,
+		  int mask, int check)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+	struct aa_audit sa;
+
+	sa.type = AA_AUDITTYPE_XATTR;
+	sa.name2 = operation;
+	sa.flags = 0;
+	sa.gfp_mask = GFP_KERNEL;
+
+	if (inode && S_ISDIR(inode->i_mode))
+		check |= AA_CHECK_DIR;
+
+	error = aa_perm_dentry(profile, dentry, mnt, &sa, mask, check);
+
+	return error;
+}
+
+/**
+ * aa_perm - basic apparmor permissions check
+ * @profile: profile to check against
+ * @dentry: dentry of the file to check
+ * @mnt: vfsmount of the file to check
+ * @mask: access mode requested
+ * @check: kind of check to perform
+ *
+ * Determine if access @mask for the file is authorized by @profile.
+ * Returns 0 on success, or else an error code.
+ */
+int aa_perm(struct aa_profile *profile, struct dentry *dentry,
+	    struct vfsmount *mnt, int mask, int check)
+{
+	struct aa_audit sa;
+	int error = 0;
+
+	if (mask == 0)
+		goto out;
+
+	sa.type = AA_AUDITTYPE_FILE;
+	sa.mask = mask;
+	sa.flags = 0;
+	sa.gfp_mask = GFP_KERNEL;
+	error = aa_perm_dentry(profile, dentry, mnt, &sa, mask, check);
+
+out:
+	return error;
+}
+
+/**
+ * aa_perm_dir
+ * @profile: profile to check against
+ * @dentry: dentry of directory to check
+ * @mnt: vfsmount of directory to check
+ * @operation: directory operation being performed
+ * @mask: access mode requested
+ *
+ * Determine if directory operation (make/remove) for dentry is authorized
+ * by @profile.
+ * Returns 0 on success, or else an error code.
+ */
+int aa_perm_dir(struct aa_profile *profile, struct dentry *dentry,
+		struct vfsmount *mnt, const char *operation, int mask)
+{
+	struct aa_audit sa;
+
+	sa.type = AA_AUDITTYPE_DIR;
+	sa.name2 = operation;
+	sa.flags = 0;
+	sa.gfp_mask = GFP_KERNEL;
+
+	return aa_perm_dentry(profile, dentry, mnt, &sa, mask, AA_CHECK_DIR);
+}
+
+int aa_perm_path(struct aa_profile *profile, const char *name, int mask)
+{
+	struct aa_audit sa;
+	int denied_mask;
+
+	sa.type = AA_AUDITTYPE_FILE;
+	sa.mask = mask;
+	sa.flags = 0;
+	sa.gfp_mask = GFP_KERNEL;
+	sa.name = name;
+
+	denied_mask = aa_file_denied(profile, name, mask);
+	aa_permerror2result(denied_mask, &sa);
+
+	return aa_audit(profile, &sa);
+}
+
+/**
+ * aa_capability - test permission to use capability
+ * @cxt: aa_task_context with profile to check against
+ * @cap: capability to be tested
+ *
+ * Look up capability in profile capability set.
+ * Returns 0 on success, or else an error code.
+ */
+int aa_capability(struct aa_task_context *cxt, int cap)
+{
+	int error = cap_raised(cxt->profile->capabilities, cap) ? 0 : -EPERM;
+	struct aa_audit sa;
+
+	/* test if cap has alread been logged */
+	if (cap_raised(cxt->caps_logged, cap)) {
+		if (PROFILE_COMPLAIN(cxt->profile))
+			error = 0;
+		return error;
+	} else
+		/* don't worry about rcu replacement of the cxt here.
+		 * caps_logged is a cache to reduce the occurance of
+		 * duplicate messages in the log.  The worst that can
+		 * happen is duplicate capability messages shows up in
+		 * the audit log
+		 */
+		cap_raise(cxt->caps_logged, cap);
+
+	sa.type = AA_AUDITTYPE_CAP;
+	sa.name = NULL;
+	sa.capability = cap;
+	sa.flags = 0;
+	sa.error_code = 0;
+	sa.result = !error;
+	sa.gfp_mask = GFP_ATOMIC;
+
+	error = aa_audit(cxt->profile, &sa);
+
+	return error;
+}
+
+/* must be used inside rcu_read_lock or task_lock */
+int aa_may_ptrace(struct aa_task_context *cxt, struct aa_profile *tracee)
+{
+	if (!cxt || cxt->profile == tracee)
+		return 0;
+	return aa_capability(cxt, CAP_SYS_PTRACE);
+}
+
+/**
+ * aa_link - hard link check
+ * @profile: profile to check against
+ * @link: dentry of link being created
+ * @link_mnt: vfsmount of link being created
+ * @target: dentry of link target
+ * @target_mnt: vfsmunt of link target
+ *
+ * Returns 0 on success, or else an error code.
+ */
+int aa_link(struct aa_profile *profile,
+	    struct dentry *link, struct vfsmount *link_mnt,
+	    struct dentry *target, struct vfsmount *target_mnt)
+{
+	int denied_mask = -EPERM, error, check = 0;
+	struct aa_audit sa;
+
+again:
+	sa.buffer = NULL;
+	sa.name = aa_get_name(link, link_mnt, &sa.buffer, check);
+	sa.buffer2 = NULL;
+	sa.name2 = aa_get_name(target, target_mnt, &sa.buffer2, check);
+
+	if (IS_ERR(sa.name)) {
+		denied_mask = PTR_ERR(sa.name);
+		sa.name = NULL;
+	}
+	if (IS_ERR(sa.name2)) {
+		denied_mask = PTR_ERR(sa.name2);
+		sa.name2 = NULL;
+	}
+
+	if (sa.name && sa.name2)
+		denied_mask = aa_link_denied(profile, sa.name, sa.name2);
+
+	aa_permerror2result(denied_mask, &sa);
+
+	sa.type = AA_AUDITTYPE_LINK;
+	sa.flags = 0;
+	sa.gfp_mask = GFP_KERNEL;
+
+	error = aa_audit(profile, &sa);
+
+	aa_put_name_buffer(sa.buffer);
+	aa_put_name_buffer(sa.buffer2);
+	if (error == -ENAMETOOLONG) {
+		BUG_ON(check & AA_CHECK_MANGLE);
+		check |= AA_CHECK_MANGLE;
+		goto again;
+	}
+
+	return error;
+}
+
+/*******************************
+ * Global task related functions
+ *******************************/
+
+/**
+ * aa_clone - initialize the task context for a new task
+ * @child: task that is being created
+ *
+ * Returns 0 on success, or else an error code.
+ */
+int aa_clone(struct task_struct *child)
+{
+	struct aa_task_context *cxt, *child_cxt;
+	struct aa_profile *profile;
+
+	if (!aa_task_context(current))
+		return 0;
+	child_cxt = aa_alloc_task_context(GFP_KERNEL);
+	if (!child_cxt)
+		return -ENOMEM;
+
+repeat:
+	profile = aa_get_profile(current);
+	if (profile) {
+		lock_profile(profile);
+		cxt = aa_task_context(current);
+		if (unlikely(profile->isstale || !cxt ||
+			     cxt->profile != profile)) {
+			/**
+			 * Race with profile replacement or removal, or with
+			 * task context removal.
+			 */
+			unlock_profile(profile);
+			aa_put_profile(profile);
+			goto repeat;
+		}
+
+		/* No need to grab the child's task lock here. */
+		aa_change_task_context(child, child_cxt, profile,
+				       cxt->hat_magic);
+		unlock_profile(profile);
+
+		if (APPARMOR_COMPLAIN(child_cxt) &&
+		    profile == null_complain_profile)
+			aa_audit_message(profile, GFP_KERNEL,
+					 "LOGPROF-HINT fork child=%d "
+					 "(%d profile %s active %s)",
+					 child->pid, current->pid,
+					 profile->parent->name, profile->name);
+		aa_put_profile(profile);
+	} else
+		aa_free_task_context(child_cxt);
+
+	return 0;
+}
+
+static struct aa_profile *
+aa_register_find(struct aa_profile *profile, const char *name, char *buffer,
+		 int mandatory, int complain)
+{
+	struct aa_profile *new_profile;
+
+	/* Locate new profile */
+	new_profile = aa_find_profile(name);
+	if (new_profile) {
+		AA_DEBUG("%s: setting profile %s\n",
+			 __FUNCTION__, new_profile->name);
+	} else if (mandatory && profile) {
+		name = mangle(name, buffer);
+		if (complain) {
+			aa_audit_message(profile, GFP_KERNEL, "LOGPROF-HINT "
+					 "missing_mandatory_profile image '%s' "
+					 "(%d profile %s active %s)",
+					 name, current->pid,
+					 profile->parent->name, profile->name);
+			profile = aa_dup_profile(null_complain_profile);
+		} else {
+			aa_audit_message(profile, GFP_KERNEL, "REJECTING "
+					 "exec(2) of image '%s'. Profile "
+					 "mandatory and not found. "
+					 "(%d profile %s active %s)",
+					 name, current->pid,
+					 profile->parent->name, profile->name);
+			return ERR_PTR(-EPERM);
+		}
+	} else {
+		/* Only way we can get into this code is if task
+		 * is unconfined.
+		 */
+		AA_DEBUG("%s: No profile found for exec image '%s'\n",
+			 __FUNCTION__,
+			 name);
+	}
+	return new_profile;
+}
+
+/**
+ * aa_register - register a new program
+ * @bprm: binprm of program being registered
+ *
+ * Try to register a new program during execve().  This should give the
+ * new program a valid aa_task_context if confined.
+ */
+int aa_register(struct linux_binprm *bprm)
+{
+	const char *filename;
+	char  *buffer = NULL;
+	struct file *filp = bprm->file;
+	struct aa_profile *profile, *old_profile, *new_profile = NULL;
+	int exec_mode = AA_EXEC_UNSAFE, complain = 0;
+
+	AA_DEBUG("%s\n", __FUNCTION__);
+
+	filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer,
+			       AA_CHECK_MANGLE);
+	if (IS_ERR(filename)) {
+		AA_ERROR("%s: Failed to get filename", __FUNCTION__);
+		return -ENOENT;
+	}
+
+repeat:
+	profile = aa_get_profile(current);
+	if (profile) {
+		complain = PROFILE_COMPLAIN(profile);
+
+		/* Confined task, determine what mode inherit, unconfined or
+		 * mandatory to load new profile
+		 */
+		exec_mode = aa_match(profile->file_rules, filename);
+
+		if (exec_mode & (MAY_EXEC | AA_EXEC_MODIFIERS)) {
+			switch (exec_mode & (MAY_EXEC | AA_EXEC_MODIFIERS)) {
+			case MAY_EXEC | AA_EXEC_INHERIT:
+				AA_DEBUG("%s: INHERIT %s\n",
+					 __FUNCTION__,
+					 filename);
+				/* nothing to be done here */
+				goto cleanup;
+
+			case MAY_EXEC | AA_EXEC_UNCONFINED:
+				AA_DEBUG("%s: UNCONFINED %s\n",
+					 __FUNCTION__,
+					 filename);
+
+				/* detach current profile */
+				new_profile = NULL;
+				break;
+
+			case MAY_EXEC | AA_EXEC_PROFILE:
+				AA_DEBUG("%s: PROFILE %s\n",
+					 __FUNCTION__,
+					 filename);
+				new_profile = aa_register_find(profile,
+							       filename,
+							       buffer, 1,
+							       complain);
+				break;
+
+			default:
+				AA_ERROR("Rejecting exec(2) of image '%s'. "
+					 "Unknown exec qualifier %x "
+					 "(%d profile %s active %s)\n",
+					 filename,
+					 exec_mode & AA_EXEC_MODIFIERS,
+					 current->pid,
+					 profile->parent->name,
+					 profile->name);
+				new_profile = ERR_PTR(-EPERM);
+				break;
+			}
+
+		} else if (complain) {
+			/* There was no entry in calling profile
+			 * describing mode to execute image in.
+			 * Drop into null-profile (disabling secure exec).
+			 */
+			new_profile = aa_dup_profile(null_complain_profile);
+			exec_mode |= AA_EXEC_UNSAFE;
+		} else {
+			filename = mangle(filename, buffer);
+			aa_audit_message(profile, GFP_KERNEL, "REJECTING "
+					 "exec(2) of image '%s'. Unable to "
+					 "determine exec qualifier. "
+					 "(%d profile %s active %s)",
+					 filename, current->pid,
+					 profile->parent->name, profile->name);
+			new_profile = ERR_PTR(-EPERM);
+		}
+	} else {
+		/* Unconfined task, load profile if it exists */
+		new_profile = aa_register_find(NULL, filename, buffer, 0, 0);
+		if (new_profile == NULL)
+			goto cleanup;
+	}
+
+	if (IS_ERR(new_profile))
+		goto cleanup;
+
+	old_profile = __aa_replace_profile(current, new_profile, 0);
+	if (IS_ERR(old_profile)) {
+		aa_put_profile(new_profile);
+		aa_put_profile(profile);
+		if (PTR_ERR(old_profile) == -ESTALE)
+			goto repeat;
+		if (PTR_ERR(old_profile) == -EPERM) {
+			filename = mangle(filename, buffer);
+			aa_audit_message(profile, GFP_KERNEL,
+					 "REJECTING exec(2) of image '%s'. "
+					 "Unable to change profile, ptraced by "
+					 "%d. (%d profile %s active %s)",
+					 filename, current->parent->pid,
+					 current->pid,
+					 profile->parent->name, profile->name);
+		}
+		new_profile = old_profile;
+		goto cleanup;
+	}
+	aa_put_profile(old_profile);
+	aa_put_profile(profile);
+
+	/* Handle confined exec.
+	 * Can be at this point for the following reasons:
+	 * 1. unconfined switching to confined
+	 * 2. confined switching to different confinement
+	 * 3. confined switching to unconfined
+	 *
+	 * Cases 2 and 3 are marked as requiring secure exec
+	 * (unless policy specified "unsafe exec")
+	 */
+	if (!(exec_mode & AA_EXEC_UNSAFE)) {
+		unsigned long bprm_flags;
+
+		bprm_flags = AA_SECURE_EXEC_NEEDED;
+		bprm->security = (void*)
+			((unsigned long)bprm->security | bprm_flags);
+	}
+
+	if (complain && new_profile == null_complain_profile)
+		aa_audit_message(new_profile, GFP_ATOMIC,
+				 "LOGPROF-HINT changing_profile "
+				 "(%d profile %s active %s)",
+				 current->pid,
+				 new_profile->parent->name, new_profile->name);
+cleanup:
+	aa_put_name_buffer(buffer);
+	if (IS_ERR(new_profile))
+		return PTR_ERR(new_profile);
+	aa_put_profile(new_profile);
+	return 0;
+}
+
+/**
+ * aa_release - release a task context
+ * @task: task being released
+ *
+ * This is called after a task has exited and the parent has reaped it.
+ */
+void aa_release(struct task_struct *task)
+{
+	struct aa_task_context *cxt;
+	struct aa_profile *profile;
+	/*
+	 * While the task context is still on a profile's task context
+	 * list, another process could replace the profile under us,
+	 * leaving us with a locked profile that is no longer attached
+	 * to this task. So after locking the profile, we check that
+	 * the profile is still attached.  The profile lock is
+	 * sufficient to prevent the replacement race so we do not lock
+	 * the task.
+	 *
+	 * lock_dep reports a false 'possible irq lock inversion dependency'
+	 * between the profile lock and the task_lock.
+	 *
+	 * We also avoid taking the task_lock here because lock_dep
+	 * would report another false {softirq-on-W} potential irq_lock
+	 * inversion.
+	 *
+	 * If the task does not have a profile attached we are safe;
+	 * nothing can race with us at this point.
+	 */
+
+repeat:
+	profile = aa_get_profile(task);
+	if (profile) {
+		lock_profile(profile);
+		cxt = aa_task_context(task);
+		if (unlikely(!cxt || cxt->profile != profile)) {
+			unlock_profile(profile);
+			aa_put_profile(profile);
+			goto repeat;
+		}
+		aa_change_task_context(task, NULL, NULL, 0);
+		unlock_profile(profile);
+		aa_put_profile(profile);
+	}
+}
+
+/**
+ * do_change_hat - actually switch hats
+ * @hat_name: name of hat to switch to
+ * @new_cxt: new aa_task_context to use on profile change
+ * @hat_magic: new magic value to use
+ *
+ * Switch to a new hat.  Returns %0 on success, error otherwise.
+ */
+static int do_change_hat(const char *hat_name,
+			 struct aa_task_context *new_cxt, u64 hat_magic)
+{
+	struct aa_task_context *cxt = aa_task_context(current);
+	struct aa_profile *sub;
+	int error = 0;
+
+	/*
+	 * Note: the profile and sub-profiles cannot go away under us here;
+	 * no need to grab an additional reference count.
+	 */
+	sub = __aa_find_profile(hat_name, &cxt->profile->parent->sub);
+
+	if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, sub))
+		return -EPERM;
+
+	if (sub) {
+		/* change hat */
+		aa_change_task_context(current, new_cxt, sub, hat_magic);
+	} else {
+		struct aa_profile *profile = cxt->profile;
+
+		if (APPARMOR_COMPLAIN(cxt)) {
+			aa_audit_message(profile, GFP_ATOMIC,
+					 "LOGPROF-HINT unknown_hat %s "
+					 "(%d profile %s active %s)",
+					 hat_name, current->pid,
+					 profile->parent->name, profile->name);
+		} else {
+			AA_DEBUG("%s: Unknown hatname '%s'. "
+				"Changing to NULL profile "
+				"(%d profile %s active %s)\n",
+				 __FUNCTION__,
+				 hat_name,
+				 current->pid,
+				 profile->parent->name,
+				 profile->name);
+			error = -EACCES;
+		}
+		/*
+		 * Switch to the NULL profile: it grants no accesses, so in
+		 * learning mode all accesses will get logged, and in enforce
+		 * mode all accesses will be denied.
+		 *
+		 * In learning mode, this allows us to learn about new hats.
+		 */
+		aa_change_task_context(current, new_cxt,
+				       cxt->profile->null_profile, hat_magic);
+	}
+
+	return error;
+}
+
+/**
+ * aa_change_hat - change hat to/from subprofile
+ * @hat_name: hat to change to
+ * @hat_magic: magic cookie to validate the hat change
+ *
+ * Change to new @hat_name, and store the @hat_magic in the current task
+ * context.  If the new @hat_name is %NULL and the @hat_magic matches that
+ * stored in the current task context and is not 0, return to the top level
+ * profile.
+ * Returns %0 on success, error otherwise.
+ */
+int aa_change_hat(const char *hat_name, u64 hat_magic)
+{
+	struct aa_task_context *cxt, *new_cxt;
+	struct aa_profile *profile = NULL;
+	int error = 0;
+
+	/* Dump out above debugging in WARN mode if we are in AUDIT mode */
+	if (APPARMOR_AUDIT(aa_task_context(current))) {
+		aa_audit_message(NULL, GFP_KERNEL, "change_hat %s, 0x%llx "
+				 "(pid %d)",
+				 hat_name ? hat_name : "NULL", hat_magic,
+				 current->pid);
+	}
+
+	new_cxt = aa_alloc_task_context(GFP_KERNEL);
+	if (!new_cxt)
+		return -ENOMEM;
+
+	cxt = lock_task_and_profiles(current, NULL);
+	if (!cxt) {
+		/* An unconfined process cannot change_hat(). */
+		error = -EPERM;
+		goto out;
+	}
+
+	/* No need to get reference count: we do not sleep. */
+	profile = cxt->profile;
+
+	/* check to see if the confined process has any hats. */
+	if (list_empty(&profile->parent->sub) && !PROFILE_COMPLAIN(profile)) {
+		error = -ECHILD;
+		goto out;
+	}
+
+	if (profile == profile->parent) {
+		/* We are in the parent profile. */
+		if (hat_name) {
+			AA_DEBUG("%s: switching to %s, 0x%llx\n",
+				 __FUNCTION__,
+				 hat_name,
+				 hat_magic);
+			error = do_change_hat(hat_name, new_cxt, hat_magic);
+		}
+	} else {
+		/*
+		 * We are in a child profile.
+		 *
+		 * Check to make sure magic is same as what was passed when
+		 * we switched into this profile.  Handle special casing of
+		 * NULL magic which confines task to subprofile and prohibits
+		 * further change_hats.
+		 */
+		if (hat_magic && hat_magic == cxt->hat_magic) {
+			if (!hat_name) {
+				/* Return from subprofile back to parent. */
+				aa_change_task_context(current, new_cxt,
+						       profile->parent, 0);
+			} else {
+				/*
+				 * Change to another (sibling) profile, and
+				 * stick with the same hat_magic.
+				 */
+				error = do_change_hat(hat_name, new_cxt,
+						      cxt->hat_magic);
+			}
+		} else if (cxt->hat_magic) {
+			AA_ERROR("KILLING process %d "
+				 "Invalid change_hat() magic# 0x%llx "
+				 "(hatname %s profile %s active %s)\n",
+				 current->pid, hat_magic,
+				 hat_name ? hat_name : "NULL",
+				 profile->parent->name,
+				 profile->name);
+
+			/* terminate current process */
+			(void)send_sig_info(SIGKILL, NULL, current);
+		} else {	/* cxt->hat_magic == 0 */
+			AA_ERROR("KILLING process %d "
+				 "Task was confined to current subprofile "
+				 "(profile %s active %s)\n",
+				 current->pid,
+				 profile->parent->name,
+				 profile->name);
+
+			/* terminate current process */
+			(void)send_sig_info(SIGKILL, NULL, current);
+		}
+
+	}
+
+out:
+	if (aa_task_context(current) != new_cxt)
+		aa_free_task_context(new_cxt);
+	task_unlock(current);
+	unlock_profile(profile);
+	return error;
+}
+
+/**
+ * __aa_replace_profile - replace a task's profile
+ * @task: task to switch the profile of
+ * @profile: profile to switch to
+ * @hat_magic: magic cookie to switch to
+ *
+ * Returns a handle to the previous profile upon success, or else an
+ * error code.
+ */
+struct aa_profile *__aa_replace_profile(struct task_struct *task,
+					struct aa_profile *profile,
+					u32 hat_magic)
+{
+	struct aa_task_context *cxt, *new_cxt = NULL;
+	struct aa_profile *old_profile = NULL;
+
+	if (profile) {
+		new_cxt = aa_alloc_task_context(GFP_KERNEL);
+		if (!new_cxt)
+			return ERR_PTR(-ENOMEM);
+	}
+
+	cxt = lock_task_and_profiles(task, profile);
+	if (unlikely(profile && profile->isstale)) {
+		task_unlock(task);
+		unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
+		aa_free_task_context(new_cxt);
+		return ERR_PTR(-ESTALE);
+	}
+
+	if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
+		task_unlock(task);
+		unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
+		aa_free_task_context(new_cxt);
+		return ERR_PTR(-EPERM);
+	}
+
+	if (cxt) {
+		old_profile = aa_dup_profile(cxt->profile);
+		aa_change_task_context(task, new_cxt, profile, cxt->hat_magic);
+	} else
+		aa_change_task_context(task, new_cxt, profile, 0);
+
+	task_unlock(task);
+	unlock_both_profiles(profile, old_profile);
+	return old_profile;
+}
+
+/**
+ * lock_task_and_profile - lock the task and confining profiles and @profile
+ * @task - task to lock
+ * @profile - extra profile to lock in addition to the current profile
+ *
+ * Handle the spinning on locking to make sure the task context and
+ * profile are consistent once all locks are aquired.
+ *
+ * return the aa_task_context currently confining the task.  The task lock
+ * will be held whether or not the task is confined.
+ */
+struct aa_task_context *
+lock_task_and_profiles(struct task_struct *task, struct aa_profile *profile)
+{
+	struct aa_task_context *cxt;
+	struct aa_profile *old_profile = NULL;
+
+	rcu_read_lock();
+repeat:
+	cxt = aa_task_context(task);
+	if (cxt)
+		old_profile = cxt->profile;
+	lock_both_profiles(profile, old_profile);
+	task_lock(task);
+
+	/* check for race with profile transition, replacement or removal */
+	if (unlikely(cxt != aa_task_context(task))) {
+		task_unlock(task);
+		unlock_both_profiles(profile, old_profile);
+		goto repeat;
+	}
+	rcu_read_unlock();
+	return cxt;
+}
+
+static void free_aa_task_context_rcu_callback(struct rcu_head *head)
+{
+	struct aa_task_context *cxt;
+
+	cxt = container_of(head, struct aa_task_context, rcu);
+	aa_free_task_context(cxt);
+}
+
+/**
+ * aa_change_task_context - switch a task to use a new context and profile
+ * @task: task that is having its task context changed
+ * @new_cxt: new task context to use after the switch
+ * @profile: new profile to use after the switch
+ * @hat_magic: hat value to switch to (0 for no hat)
+ */
+void aa_change_task_context(struct task_struct *task,
+			    struct aa_task_context *new_cxt,
+			    struct aa_profile *profile, u64 hat_magic)
+{
+	struct aa_task_context *old_cxt = aa_task_context(task);
+
+	if (old_cxt) {
+		list_del_init(&old_cxt->list);
+		call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
+	}
+	if (new_cxt) {
+		/* clear the caps_logged cache, so that new profile/hat has
+		 * chance to emit its own set of cap messages */
+		new_cxt->caps_logged = CAP_EMPTY_SET;
+		new_cxt->hat_magic = hat_magic;
+		new_cxt->task = task;
+		new_cxt->profile = aa_dup_profile(profile);
+		list_move(&new_cxt->list, &profile->parent->task_contexts);
+	}
+	rcu_assign_pointer(task->security, new_cxt);
+}

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (36 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 37/45] AppArmor: Main Part jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-15  9:14   ` Pavel Machek
  2007-05-14 11:06 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching jjohansen
                   ` (7 subsequent siblings)
  45 siblings, 1 reply; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, John Johansen, Andreas Gruenbacher

[-- Attachment #1: apparmor-lsm.diff --]
[-- Type: text/plain, Size: 20806 bytes --]

Module parameters, LSM hooks, initialization and teardown.

Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

Index: b/security/apparmor/lsm.c
===================================================================
--- /dev/null
+++ b/security/apparmor/lsm.c
@@ -0,0 +1,790 @@
+/*
+ *	Copyright (C) 1998-2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor LSM interface
+ */
+
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+
+#include "apparmor.h"
+#include "inline.h"
+
+static int param_set_aabool(const char *val, struct kernel_param *kp);
+static int param_get_aabool(char *buffer, struct kernel_param *kp);
+#define param_check_aabool(name, p) __param_check(name, p, int)
+
+static int param_set_aauint(const char *val, struct kernel_param *kp);
+static int param_get_aauint(char *buffer, struct kernel_param *kp);
+#define param_check_aauint(name, p) __param_check(name, p, int)
+
+/* Flag values, also controllable via /sys/module/apparmor/parameters
+ * We define special types as we want to do additional mediation.
+ *
+ * Complain mode -- in complain mode access failures result in auditing only
+ * and task is allowed access.  audit events are processed by userspace to
+ * generate policy.  Default is 'enforce' (0).
+ * Value is also togglable per profile and referenced when global value is
+ * enforce.
+ */
+int apparmor_complain = 0;
+module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
+
+/* Debug mode */
+int apparmor_debug = 0;
+module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
+
+/* Audit mode */
+int apparmor_audit = 0;
+module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
+
+/* Syscall logging mode */
+int apparmor_logsyscall = 0;
+module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
+
+/* Maximum pathname length before accesses will start getting rejected */
+unsigned int apparmor_path_max = 2 * PATH_MAX;
+module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
+
+static int param_set_aabool(const char *val, struct kernel_param *kp)
+{
+	if (aa_task_context(current))
+		return -EPERM;
+	return param_set_bool(val, kp);
+}
+
+static int param_get_aabool(char *buffer, struct kernel_param *kp)
+{
+	if (aa_task_context(current))
+		return -EPERM;
+	return param_get_bool(buffer, kp);
+}
+
+static int param_set_aauint(const char *val, struct kernel_param *kp)
+{
+	if (aa_task_context(current))
+		return -EPERM;
+	return param_set_uint(val, kp);
+}
+
+static int param_get_aauint(char *buffer, struct kernel_param *kp)
+{
+	if (aa_task_context(current))
+		return -EPERM;
+	return param_get_uint(buffer, kp);
+}
+
+static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
+			     const char *name)
+{
+	struct aa_profile *profile = aa_get_profile(task);
+	int error = 0;
+
+	if (profile) {
+		error = aa_audit_syscallreject(profile, flags, name);
+		aa_put_profile(profile);
+	}
+
+	return error;
+}
+
+static int apparmor_ptrace(struct task_struct *parent,
+			   struct task_struct *child)
+{
+	struct aa_task_context *cxt;
+	struct aa_task_context *child_cxt;
+	struct aa_profile *child_profile;
+	int error = 0;
+
+	/*
+	 * parent can ptrace child when
+	 * - parent is unconfined
+	 * - parent & child are in the same namespace &&
+	 *   - parent is in complain mode
+	 *   - parent and child are confined by the same profile
+	 *   - parent profile has CAP_SYS_PTRACE
+	 */
+
+	rcu_read_lock();
+	cxt = aa_task_context(parent);
+	child_cxt = aa_task_context(child);
+	child_profile = child_cxt ? child_cxt->profile : NULL;
+	if (cxt && (parent->nsproxy != child->nsproxy)) {
+		aa_audit_message(NULL, GFP_ATOMIC, "REJECTING ptrace across "
+				 "namespace of %d by %d",
+				 parent->pid, child->pid);
+		error = -EPERM;
+	} else {
+		error = aa_may_ptrace(cxt, child_profile);
+		if (cxt && PROFILE_COMPLAIN(cxt->profile)) {
+			aa_audit_message(cxt->profile, GFP_ATOMIC,
+					 "LOGPROF-HINT ptrace pid=%d child=%d "
+					 "(%d profile %s active %s)",
+					 current->pid, child->pid, current->pid,
+					 cxt->profile->parent->name,
+					 cxt->profile->name);
+		}
+	}
+	rcu_read_unlock();
+
+	return error;
+}
+
+static int apparmor_capable(struct task_struct *task, int cap)
+{
+	int error;
+
+	/* cap_capable returns 0 on success, else -EPERM */
+	error = cap_capable(task, cap);
+
+	if (!error) {
+		struct aa_task_context *cxt;
+
+		rcu_read_lock();
+		cxt = aa_task_context(task);
+		if (cxt)
+			error = aa_capability(cxt, cap);
+		rcu_read_unlock();
+	}
+
+	return error;
+}
+
+static int apparmor_sysctl(struct ctl_table *table, int op)
+{
+	struct aa_profile *profile = aa_get_profile(current);
+	int error = 0;
+
+	if (profile) {
+		char *buffer, *name;
+		int mask;
+
+		mask = 0;
+		if (op & 4)
+			mask |= MAY_READ;
+		if (op & 2)
+			mask |= MAY_WRITE;
+
+		error = -ENOMEM;
+		buffer = (char*)__get_free_page(GFP_KERNEL);
+		if (!buffer)
+			goto out;
+		name = sysctl_pathname(table, buffer, PAGE_SIZE);
+		if (name && name - buffer >= 5) {
+			name -= 5;
+			memcpy(name, "/proc", 5);
+			error = aa_perm_path(profile, name, mask);
+		}
+		free_page((unsigned long)buffer);
+	}
+
+out:
+	return error;
+}
+
+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
+{
+	/* handle capability bits with setuid, etc */
+	cap_bprm_set_security(bprm);
+	/* already set based on script name */
+	if (bprm->sh_bang)
+		return 0;
+	return aa_register(bprm);
+}
+
+static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
+{
+	int ret = cap_bprm_secureexec(bprm);
+
+	if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
+		AA_DEBUG("%s: secureexec required for %s\n",
+			 __FUNCTION__, bprm->filename);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
+			      unsigned long flags, void *data)
+{
+	return aa_reject_syscall(current, GFP_KERNEL, "mount");
+}
+
+static int apparmor_umount(struct vfsmount *mnt, int flags)
+{
+	return aa_reject_syscall(current, GFP_KERNEL, "umount");
+}
+
+static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
+				struct vfsmount *mnt, int mask)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	if (!mnt || !mediated_filesystem(dir))
+		goto out;
+
+	profile = aa_get_profile(current);
+
+	if (profile)
+		error = aa_perm_dir(profile, dentry, mnt, "mkdir", MAY_WRITE);
+
+	aa_put_profile(profile);
+
+out:
+	return error;
+}
+
+static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
+				struct vfsmount *mnt)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	if (!mnt || !mediated_filesystem(dir))
+		goto out;
+
+	profile = aa_get_profile(current);
+
+	if (profile)
+		error = aa_perm_dir(profile, dentry, mnt, "rmdir", MAY_WRITE);
+
+	aa_put_profile(profile);
+
+out:
+	return error;
+}
+
+static int aa_permission(struct inode *inode, struct dentry *dentry,
+			 struct vfsmount *mnt, int mask, int check)
+{
+	int error = 0;
+
+	if (mnt && mediated_filesystem(inode)) {
+		struct aa_profile *profile;
+
+		profile = aa_get_profile(current);
+		if (profile)
+			error = aa_perm(profile, dentry, mnt, mask, check);
+		aa_put_profile(profile);
+	}
+	return error;
+}
+
+static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
+				 struct vfsmount *mnt, int mask)
+{
+	return aa_permission(dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_link(struct dentry *old_dentry,
+			       struct vfsmount *old_mnt, struct inode *dir,
+			       struct dentry *new_dentry,
+			       struct vfsmount *new_mnt)
+{
+	int error = 0;
+	struct aa_profile *profile;
+
+	if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
+		goto out;
+
+	profile = aa_get_profile(current);
+
+	if (profile)
+		error = aa_link(profile, new_dentry, new_mnt,
+				old_dentry, old_mnt);
+
+	aa_put_profile(profile);
+
+out:
+	return error;
+}
+
+static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
+				 struct vfsmount *mnt)
+{
+	int check = 0;
+
+	if (S_ISDIR(dentry->d_inode->i_mode))
+		check |= AA_CHECK_DIR;
+	return aa_permission(dir, dentry, mnt, MAY_WRITE, check);
+}
+
+static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
+				  struct vfsmount *mnt, const char *old_name)
+{
+	return aa_permission(dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
+				struct vfsmount *mnt, int mode, dev_t dev)
+{
+	return aa_permission(dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_rename(struct inode *old_dir,
+				 struct dentry *old_dentry,
+				 struct vfsmount *old_mnt,
+				 struct inode *new_dir,
+				 struct dentry *new_dentry,
+				 struct vfsmount *new_mnt)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
+		goto out;
+
+	profile = aa_get_profile(current);
+
+	if (profile) {
+		struct inode *inode = old_dentry->d_inode;
+		int check = 0;
+
+		if (inode && S_ISDIR(inode->i_mode))
+			check |= AA_CHECK_DIR;
+		if (old_mnt)
+			error = aa_perm(profile, old_dentry, old_mnt,
+					MAY_READ | MAY_WRITE, check);
+
+		if (!error && new_mnt) {
+			error = aa_perm(profile, new_dentry, new_mnt,
+					MAY_WRITE, check);
+		}
+	}
+
+	aa_put_profile(profile);
+
+out:
+	return error;
+}
+
+static int apparmor_inode_permission(struct inode *inode, int mask,
+				     struct nameidata *nd)
+{
+	int check = 0;
+
+	if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
+		return 0;
+	mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
+	if (S_ISDIR(inode->i_mode)) {
+		check |= AA_CHECK_DIR;
+		/* allow traverse accesses to directories */
+		mask &= ~MAY_EXEC;
+	}
+	return aa_permission(inode, nd->dentry, nd->mnt, mask, check);
+}
+
+static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
+				  struct iattr *iattr)
+{
+	int error = 0;
+
+	if (!mnt)
+		goto out;
+
+	if (mediated_filesystem(dentry->d_inode)) {
+		struct aa_profile *profile;
+
+		profile = aa_get_profile(current);
+		/*
+		 * Mediate any attempt to change attributes of a file
+		 * (chmod, chown, chgrp, etc)
+		 */
+		if (profile)
+			error = aa_attr(profile, dentry, mnt, iattr);
+
+		aa_put_profile(profile);
+	}
+
+out:
+	return error;
+}
+
+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
+			       const char *operation, int mask,
+			       struct file *file)
+{
+	int error = 0;
+
+	if (mnt && mediated_filesystem(dentry->d_inode)) {
+		struct aa_profile *profile = aa_get_profile(current);
+		int check = file ? AA_CHECK_FD : 0;
+
+		if (profile)
+			error = aa_perm_xattr(profile, dentry, mnt, operation,
+					      mask, check);
+		aa_put_profile(profile);
+	}
+
+	return error;
+}
+
+static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+				   char *name, void *value, size_t size,
+				   int flags, struct file *file)
+{
+	return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
+}
+
+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+				   char *name, struct file *file)
+{
+	return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
+}
+
+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
+				    struct file *file)
+{
+	return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
+}
+
+static int apparmor_inode_removexattr(struct dentry *dentry,
+				      struct vfsmount *mnt, char *name,
+				      struct file *file)
+{
+	return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
+				   file);
+}
+
+static int apparmor_file_permission(struct file *file, int mask)
+{
+	struct aa_profile *profile;
+	struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
+	int error = 0;
+
+	if (!file_profile)
+		goto out;
+
+	/*
+	 * If this file was opened under a different profile, we
+	 * revalidate the access against the current profile.
+	 */
+	profile = aa_get_profile(current);
+	if (profile && file_profile != profile) {
+		struct dentry *dentry = file->f_dentry;
+		struct vfsmount *mnt = file->f_vfsmnt;
+		struct inode *inode = dentry->d_inode;
+		int check = AA_CHECK_FD;
+
+		/*
+		 * FIXME: We should remember which profiles we revalidated
+		 *	  against.
+		 */
+		if (S_ISDIR(inode->i_mode))
+			check |= AA_CHECK_DIR;
+		mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
+		error = aa_permission(inode, dentry, mnt, mask, check);
+	}
+	aa_put_profile(profile);
+
+out:
+	return error;
+}
+
+static int apparmor_file_alloc_security(struct file *file)
+{
+	struct aa_profile *profile;
+
+	profile = aa_get_profile(current);
+	if (profile)
+		file->f_security = profile;
+
+	return 0;
+}
+
+static void apparmor_file_free_security(struct file *file)
+{
+	struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
+
+	aa_put_profile(file_profile);
+}
+
+static inline int aa_mmap(struct file *file, unsigned long prot,
+			  unsigned long flags)
+{
+	struct dentry *dentry;
+	int mask = 0;
+
+	if (!file || !file->f_security)
+		return 0;
+
+	if (prot & PROT_READ)
+		mask |= MAY_READ;
+	/* Private mappings don't require write perms since they don't
+	 * write back to the files */
+	if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
+		mask |= MAY_WRITE;
+	if (prot & PROT_EXEC)
+		mask |= AA_EXEC_MMAP;
+
+	dentry = file->f_dentry;
+	return aa_permission(dentry->d_inode, dentry, file->f_vfsmnt, mask,
+			     AA_CHECK_FD);
+}
+
+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
+			       unsigned long prot, unsigned long flags)
+{
+	return aa_mmap(file, prot, flags);
+}
+
+static int apparmor_file_mprotect(struct vm_area_struct *vma,
+				  unsigned long reqprot, unsigned long prot)
+{
+	return aa_mmap(vma->vm_file, prot,
+		       !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
+}
+
+static int apparmor_task_alloc_security(struct task_struct *task)
+{
+	return aa_clone(task);
+}
+
+/*
+ * Called from IRQ context from RCU callback.
+ */
+static void apparmor_task_free_security(struct task_struct *task)
+{
+	aa_release(task);
+}
+
+static int apparmor_getprocattr(struct task_struct *task, char *name,
+				char **value)
+{
+	unsigned len;
+	int error;
+	struct aa_profile *profile;
+
+	/* AppArmor only supports the "current" process attribute */
+	if (strcmp(name, "current") != 0)
+		return -EINVAL;
+
+	/* must be task querying itself or admin */
+	if (current != task && !capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	profile = aa_get_profile(task);
+	error = aa_getprocattr(profile, value, &len);
+	aa_put_profile(profile);
+	if (!error)
+		error = len;
+
+	return error;
+}
+
+static int apparmor_setprocattr(struct task_struct *task, char *name,
+				void *value, size_t size)
+{
+	char *command, *args;
+	int error;
+
+	if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
+		return -EINVAL;
+	args = value;
+	args[size] = '\0';
+	args = strstrip(args);
+	command = strsep(&args, " ");
+	if (!args)
+		return -EINVAL;
+	while (isspace(*args))
+		args++;
+	if (!*args)
+		return -EINVAL;
+
+	if (strcmp(command, "changehat") == 0) {
+		if (current != task)
+			return -EACCES;
+		error = aa_setprocattr_changehat(args);
+	} else if (strcmp(command, "setprofile")) {
+		struct aa_profile *profile;
+
+		/* Only an unconfined process with admin capabilities
+		 * may change the profile of another task.
+		 */
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EACCES;
+
+		profile = aa_get_profile(current);
+		if (profile) {
+			aa_put_profile(profile);
+			aa_audit_message(NULL, GFP_KERNEL, "Attempt by "
+					 "confined task %d [user %d] to "
+					 "assign profile to task %d",
+					 current->pid, current->uid,
+					 task->pid);
+			return -EACCES;
+		}
+		error = aa_setprocattr_setprofile(task, args);
+	} else {
+		AA_ERROR("Unknown setprocattr command '%.*s' "
+			"by task %d [user %d] for task %d",
+			size < 16 ? (int)size : 16,
+			command,
+			current->pid,
+			current->uid,
+			task->pid);
+		error = -EINVAL;
+	}
+
+	if (!error)
+		error = size;
+	return error;
+}
+
+struct security_operations apparmor_ops = {
+	.ptrace =			apparmor_ptrace,
+	.capget =			cap_capget,
+	.capset_check =			cap_capset_check,
+	.capset_set =			cap_capset_set,
+	.sysctl =			apparmor_sysctl,
+	.capable =			apparmor_capable,
+	.syslog =			cap_syslog,
+
+	.netlink_send =			cap_netlink_send,
+	.netlink_recv =			cap_netlink_recv,
+
+	.bprm_apply_creds =		cap_bprm_apply_creds,
+	.bprm_set_security =		apparmor_bprm_set_security,
+	.bprm_secureexec =		apparmor_bprm_secureexec,
+
+	.sb_mount =			apparmor_sb_mount,
+	.sb_umount =			apparmor_umount,
+
+	.inode_mkdir =			apparmor_inode_mkdir,
+	.inode_rmdir =			apparmor_inode_rmdir,
+	.inode_create =			apparmor_inode_create,
+	.inode_link =			apparmor_inode_link,
+	.inode_unlink =			apparmor_inode_unlink,
+	.inode_symlink =		apparmor_inode_symlink,
+	.inode_mknod =			apparmor_inode_mknod,
+	.inode_rename =			apparmor_inode_rename,
+	.inode_permission =		apparmor_inode_permission,
+	.inode_setattr =		apparmor_inode_setattr,
+	.inode_setxattr =		apparmor_inode_setxattr,
+	.inode_getxattr =		apparmor_inode_getxattr,
+	.inode_listxattr =		apparmor_inode_listxattr,
+	.inode_removexattr =		apparmor_inode_removexattr,
+	.file_permission =		apparmor_file_permission,
+	.file_alloc_security =		apparmor_file_alloc_security,
+	.file_free_security =		apparmor_file_free_security,
+	.file_mmap =			apparmor_file_mmap,
+	.file_mprotect =		apparmor_file_mprotect,
+
+	.task_alloc_security =		apparmor_task_alloc_security,
+	.task_free_security =		apparmor_task_free_security,
+	.task_post_setuid =		cap_task_post_setuid,
+	.task_reparent_to_init =	cap_task_reparent_to_init,
+
+	.getprocattr =			apparmor_getprocattr,
+	.setprocattr =			apparmor_setprocattr,
+};
+
+static void info_message(const char *str)
+{
+	printk(KERN_INFO "AppArmor: %s", str);
+	aa_audit_message(NULL, GFP_KERNEL, "%s", str);
+}
+
+static int __init apparmor_init(void)
+{
+	int error;
+
+	if ((error = create_apparmorfs())) {
+		AA_ERROR("Unable to activate AppArmor filesystem\n");
+		goto createfs_out;
+	}
+
+	if ((error = alloc_null_complain_profile())){
+		AA_ERROR("Unable to allocate null complain profile\n");
+		goto alloc_out;
+	}
+
+	if ((error = register_security(&apparmor_ops))) {
+		AA_ERROR("Unable to load AppArmor\n");
+		goto register_security_out;
+	}
+
+	if (apparmor_complain)
+		info_message("AppArmor initialized: complainmode enabled");
+	else
+		info_message("AppArmor initialized");
+
+	return error;
+
+register_security_out:
+	free_null_complain_profile();
+
+alloc_out:
+	destroy_apparmorfs();
+
+createfs_out:
+	return error;
+
+}
+
+static void __exit apparmor_exit(void)
+{
+	/* Remove and release all the profiles on the profile list. */
+	mutex_lock(&aa_interface_lock);
+	write_lock(&profile_list_lock);
+	while (!list_empty(&profile_list)) {
+		struct aa_profile *profile =
+			list_entry(profile_list.next, struct aa_profile, list);
+
+		/* Remove the profile from each task context it is on. */
+		lock_profile(profile);
+		profile->isstale = 1;
+		aa_unconfine_tasks(profile);
+		unlock_profile(profile);
+
+		/* Release the profile itself. */
+		list_del_init(&profile->list);
+		aa_put_profile(profile);
+	}
+	write_unlock(&profile_list_lock);
+
+	/* FIXME: cleanup profiles references on files */
+
+	free_null_complain_profile();
+
+	/*
+	 * Delay for an rcu cycle to make sure that all active task
+	 * context readers have finished, and all profiles have been
+	 * freed by their rcu callbacks.
+	 */
+	synchronize_rcu();
+
+	destroy_apparmorfs();
+	mutex_unlock(&aa_interface_lock);
+
+	if (unregister_security(&apparmor_ops))
+		info_message("Unable to properly unregister AppArmor");
+
+	info_message("AppArmor protection removed");
+}
+
+module_init(apparmor_init);
+module_exit(apparmor_exit);
+
+MODULE_DESCRIPTION("AppArmor process confinement");
+MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
+MODULE_LICENSE("GPL");

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (37 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 38/45] AppArmor: Module and LSM hooks jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-15  9:20   ` Pavel Machek
  2007-05-14 11:06 ` [AppArmor 40/45] AppArmor: all the rest jjohansen
                   ` (6 subsequent siblings)
  45 siblings, 1 reply; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, John Johansen, Andreas Gruenbacher

[-- Attachment #1: apparmor-module_interface.diff --]
[-- Type: text/plain, Size: 25238 bytes --]

Pathname matching, transition table loading, profile loading and
manipulation.

Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 security/apparmor/match.c            |  232 ++++++++++++
 security/apparmor/match.h            |   83 ++++
 security/apparmor/module_interface.c |  643 +++++++++++++++++++++++++++++++++++
 3 files changed, 958 insertions(+)

--- /dev/null
+++ b/security/apparmor/match.c
@@ -0,0 +1,232 @@
+/*
+ *	Copyright (C) 2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	Regular expression transition table matching
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include "match.h"
+
+static struct table_header *unpack_table(void *blob, size_t bsize)
+{
+	struct table_header *table = NULL;
+	struct table_header th;
+	size_t tsize;
+
+	if (bsize < sizeof(struct table_header))
+		goto out;
+
+	th.td_id = be16_to_cpu(*(u16 *) (blob));
+	th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
+	th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
+	blob += sizeof(struct table_header);
+
+	if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
+		th.td_flags == YYTD_DATA8))
+		goto out;
+
+	tsize = table_size(th.td_lolen, th.td_flags);
+	if (bsize < tsize)
+		goto out;
+
+	table = kmalloc(tsize, GFP_KERNEL);
+	if (table) {
+		*table = th;
+		if (th.td_flags == YYTD_DATA8)
+			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
+				     u8, byte_to_byte);
+		else if (th.td_flags == YYTD_DATA16)
+			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
+				     u16, be16_to_cpu);
+		else
+			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
+				     u32, be32_to_cpu);
+	}
+
+out:
+	return table;
+}
+
+int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
+{
+	int hsize, i;
+	int error = -ENOMEM;
+
+	/* get dfa table set header */
+	if (size < sizeof(struct table_set_header))
+		goto fail;
+
+	if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
+		goto fail;
+
+	hsize = ntohl(*(u32 *)(blob + 4));
+	if (size < hsize)
+		goto fail;
+
+	blob += hsize;
+	size -= hsize;
+
+	error = -EPROTO;
+	while (size > 0) {
+		struct table_header *table;
+		table = unpack_table(blob, size);
+		if (!table)
+			goto fail;
+
+		switch(table->td_id) {
+		case YYTD_ID_ACCEPT:
+		case YYTD_ID_BASE:
+			dfa->tables[table->td_id - 1] = table;
+			if (table->td_flags != YYTD_DATA32)
+				goto fail;
+			break;
+		case YYTD_ID_DEF:
+		case YYTD_ID_NXT:
+		case YYTD_ID_CHK:
+			dfa->tables[table->td_id - 1] = table;
+			if (table->td_flags != YYTD_DATA16)
+				goto fail;
+			break;
+		case YYTD_ID_EC:
+			dfa->tables[table->td_id - 1] = table;
+			if (table->td_flags != YYTD_DATA8)
+				goto fail;
+			break;
+		default:
+			kfree(table);
+			goto fail;
+		}
+
+		blob += table_size(table->td_lolen, table->td_flags);
+		size -= table_size(table->td_lolen, table->td_flags);
+	}
+
+	return 0;
+
+fail:
+	for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
+		if (dfa->tables[i]) {
+			kfree(dfa->tables[i]);
+			dfa->tables[i] = NULL;
+		}
+	}
+	return error;
+}
+
+/**
+ * verify_dfa - verify that all the transitions and states in the dfa tables
+ *              are in bounds.
+ * @dfa: dfa to test
+ *
+ * assumes dfa has gone through the verification done by unpacking
+ */
+int verify_dfa(struct aa_dfa *dfa)
+{
+	size_t i, state_count, trans_count;
+	int error = -EPROTO;
+
+	/* check that required tables exist */
+	if (!(dfa->tables[YYTD_ID_ACCEPT -1 ] &&
+	      dfa->tables[YYTD_ID_DEF - 1] &&
+	      dfa->tables[YYTD_ID_BASE - 1] &&
+	      dfa->tables[YYTD_ID_NXT - 1] &&
+	      dfa->tables[YYTD_ID_CHK - 1]))
+		goto out;
+
+	/* accept.size == default.size == base.size */
+	state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
+	if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
+	      state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen))
+		goto out;
+
+	/* next.size == chk.size */
+	trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
+	if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
+		goto out;
+
+	/* if equivalence classes then its table size must be 256 */
+	if (dfa->tables[YYTD_ID_EC - 1] &&
+	    dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
+		goto out;
+
+	for (i = 0; i < state_count; i++) {
+		if (DEFAULT_TABLE(dfa)[i] >= state_count)
+			goto out;
+		if (BASE_TABLE(dfa)[i] >= trans_count + 256)
+			goto out;
+	}
+
+	for (i = 0; i < trans_count ; i++) {
+		if (NEXT_TABLE(dfa)[i] >= state_count)
+			goto out;
+		if (CHECK_TABLE(dfa)[i] >= state_count)
+			goto out;
+	}
+
+	error = 0;
+out:
+	return error;
+}
+
+struct aa_dfa *aa_match_alloc(void)
+{
+	return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
+}
+
+void aa_match_free(struct aa_dfa *dfa)
+{
+	if (dfa) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
+			kfree(dfa->tables[i]);
+	}
+	kfree(dfa);
+}
+
+/**
+ * aa_dfa_match - match @path against @dfa starting in @state
+ * @dfa: the dfa to match @path against
+ * @state: the state to start matching in
+ * @path: the path to match against the dfa
+ *
+ * aa_dfa_match will match the full path length and return the state it
+ * finished matching in. The final state is used to look up the accepting
+ * label.
+ */
+unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str)
+{
+	u16 *def = DEFAULT_TABLE(dfa);
+	u32 *base = BASE_TABLE(dfa);
+	u16 *next = NEXT_TABLE(dfa);
+	u16 *check = CHECK_TABLE(dfa);
+	unsigned int state = 1, pos;
+
+	/* current state is <state>, matching character *str */
+	if (dfa->tables[YYTD_ID_EC - 1]) {
+		u8 *equiv = EQUIV_TABLE(dfa);
+		while (*str) {
+			pos = base[state] + equiv[(u8)*str++];
+			if (check[pos] == state)
+				state = next[pos];
+			else
+				state = def[state];
+		}
+	} else {
+		while (*str) {
+			pos = base[state] + (u8)*str++;
+			if (check[pos] == state)
+				state = next[pos];
+			else
+				state = def[state];
+		}
+	}
+	return ACCEPT_TABLE(dfa)[state];
+}
--- /dev/null
+++ b/security/apparmor/match.h
@@ -0,0 +1,83 @@
+/*
+ *	Copyright (C) 2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor submodule (match) prototypes
+ */
+
+#ifndef __MATCH_H
+#define __MATCH_H
+
+/**
+ * The format used for transition tables is based on the GNU flex table
+ * file format (--tables-file option; see Table File Format in the flex
+ * info pages and the flex sources for documentation). The magic number
+ * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
+ * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
+ * slightly differently (see the apparmor-parser package).
+ */
+
+#define YYTH_MAGIC	0x1B5E783D
+
+struct table_set_header {
+	u32		th_magic;	/* YYTH_MAGIC */
+	u32		th_hsize;
+	u32		th_ssize;
+	u16		th_flags;
+	char		th_version[];
+};
+
+#define	YYTD_ID_ACCEPT	1
+#define YYTD_ID_BASE	2
+#define YYTD_ID_CHK	3
+#define YYTD_ID_DEF	4
+#define YYTD_ID_EC	5
+#define YYTD_ID_META	6
+#define YYTD_ID_NXT	8
+
+
+#define YYTD_DATA8	1
+#define YYTD_DATA16	2
+#define YYTD_DATA32	4
+
+struct table_header {
+	u16		td_id;
+	u16		td_flags;
+	u32		td_hilen;
+	u32		td_lolen;
+	char		td_data[];
+};
+
+#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data))
+#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data))
+#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data))
+#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
+#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
+#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
+
+struct aa_dfa {
+	struct table_header *tables[YYTD_ID_NXT];
+};
+
+#define byte_to_byte(X) (X)
+
+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
+	do { \
+		typeof(LEN) __i; \
+		TYPE *__t = (TYPE *) TABLE; \
+		TYPE *__b = (TYPE *) BLOB; \
+		for (__i = 0; __i < LEN; __i++) { \
+			__t[__i] = NTOHX(__b[__i]); \
+		} \
+	} while (0)
+
+static inline size_t table_size(size_t len, size_t el_size)
+{
+	return ALIGN(sizeof(struct table_header) + len * el_size, 8);
+}
+
+#endif /* __MATCH_H */
--- /dev/null
+++ b/security/apparmor/module_interface.c
@@ -0,0 +1,643 @@
+/*
+ *	Copyright (C) 1998-2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor userspace policy interface
+ */
+
+#include <asm/unaligned.h>
+
+#include "apparmor.h"
+#include "inline.h"
+
+/*
+ * This mutex is used to synchronize profile adds, replacements, and
+ * removals: we only allow one of these operations at a time.
+ * We do not use the profile list lock here in order to avoid blocking
+ * exec during those operations.  (Exec involves a profile list lookup
+ * for named-profile transitions.)
+ */
+DEFINE_MUTEX(aa_interface_lock);
+
+/*
+ * The AppArmor interface treats data as a type byte followed by the
+ * actual data.  The interface has the notion of a a named entry
+ * which has a name (AA_NAME typecode followed by name string) followed by
+ * the entries typecode and data.  Named types allow for optional
+ * elements and extensions to be added and tested for without breaking
+ * backwards compatability.
+ */
+
+enum aa_code {
+	AA_U8,
+	AA_U16,
+	AA_U32,
+	AA_U64,
+	AA_NAME,	/* same as string except it is items name */
+	AA_STRING,
+	AA_BLOB,
+	AA_STRUCT,
+	AA_STRUCTEND,
+	AA_LIST,
+	AA_LISTEND,
+};
+
+/*
+ * aa_ext is the read of the buffer containing the serialized profile.  The
+ * data is copied into a kernel buffer in apparmorfs and then handed off to
+ * the unpack routines.
+ */
+struct aa_ext {
+	void *start;
+	void *end;
+	void *pos;	/* pointer to current position in the buffer */
+	u32 version;
+};
+
+static inline int aa_inbounds(struct aa_ext *e, size_t size)
+{
+	return (size <= e->end - e->pos);
+}
+
+/**
+ * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
+ * @e: serialized data read head
+ * @chunk: start address for chunk of data
+ *
+ * return the size of chunk found with the read head at the end of
+ * the chunk.
+ */
+static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
+{
+	void *pos = e->pos;
+	size_t size = 0;
+
+	if (!aa_inbounds(e, sizeof(u16)))
+		goto fail;
+	size = le16_to_cpu(get_unaligned((u16 *)e->pos));
+	e->pos += sizeof(u16);
+	if (!aa_inbounds(e, size))
+		goto fail;
+	*chunk = e->pos;
+	e->pos += size;
+	return size;
+
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
+{
+	if (!aa_inbounds(e, 1))
+		return 0;
+	if (*(u8 *) e->pos != code)
+		return 0;
+	e->pos++;
+	return 1;
+}
+
+/**
+ * aa_is_nameX - check is the next element is of type X with a name of @name
+ * @e: serialized data extent information
+ * @code: type code
+ * @name: name to match to the serialized element.
+ *
+ * check that the next serialized data element is of type X and has a tag
+ * name @name.  If @name is specified then there must be a matching
+ * name element in the stream.  If @name is NULL any name element will be
+ * skipped and only the typecode will be tested.
+ * returns 1 on success (both type code and name tests match) and the read
+ * head is advanced past the headers
+ * returns %0 if either match failes, the read head does not move
+ */
+static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
+{
+	void *pos = e->pos;
+	/*
+	 * Check for presence of a tagname, and if present name size
+	 * AA_NAME tag value is a u16.
+	 */
+	if (aa_is_X(e, AA_NAME)) {
+		char *tag;
+		size_t size = aa_is_u16_chunk(e, &tag);
+		/* if a name is specified it must match. otherwise skip tag */
+		if (name && (!size || strcmp(name, tag)))
+			goto fail;
+	} else if (name) {
+		/* if a name is specified and there is no name tag fail */
+		goto fail;
+	}
+
+	/* now check if type code matches */
+	if (aa_is_X(e, code))
+		return 1;
+
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
+{
+	void *pos = e->pos;
+	if (aa_is_nameX(e, AA_U32, name)) {
+		if (!aa_inbounds(e, sizeof(u32)))
+			goto fail;
+		if (data)
+			*data = le32_to_cpu(get_unaligned((u32 *)e->pos));
+		e->pos += sizeof(u32);
+		return 1;
+	}
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
+{
+	void *pos = e->pos;
+	if (aa_is_nameX(e, AA_BLOB, name)) {
+		u32 size;
+		if (!aa_inbounds(e, sizeof(u32)))
+			goto fail;
+		size = le32_to_cpu(get_unaligned((u32 *)e->pos));
+		e->pos += sizeof(u32);
+		if (aa_inbounds(e, (size_t) size)) {
+			* blob = e->pos;
+			e->pos += size;
+			return size;
+		}
+	}
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
+{
+	char *src_str;
+	size_t size = 0;
+	void *pos = e->pos;
+	*string = NULL;
+	if (aa_is_nameX(e, AA_STRING, name) &&
+	    (size = aa_is_u16_chunk(e, &src_str))) {
+		char *str;
+		if (!(str = kmalloc(size, GFP_KERNEL)))
+			goto fail;
+		memcpy(str, src_str, size);
+		*string = str;
+	}
+
+	return size;
+
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+/**
+ * aa_unpack_dfa - unpack a file rule dfa
+ * @e: serialized data extent information
+ *
+ * returns dfa or ERR_PTR
+ */
+struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
+{
+	char *blob = NULL;
+	size_t size, error = 0;
+	struct aa_dfa *dfa = NULL;
+
+	size = aa_is_blob(e, &blob, "aadfa");
+	if (size) {
+		dfa = aa_match_alloc();
+		if (dfa) {
+			/*
+			 * The dfa is aligned with in the blob to 8 bytes
+			 * from the beginning of the stream.
+			 */
+			size_t sz = blob - (char *) e->start;
+			size_t pad = ALIGN(sz, 8) - sz;
+			error = unpack_dfa(dfa, blob + pad, size - pad);
+			if (!error)
+				error = verify_dfa(dfa);
+		} else {
+			error = -ENOMEM;
+		}
+
+		if (error) {
+			aa_match_free(dfa);
+			dfa = ERR_PTR(error);
+		}
+	}
+
+	return dfa;
+}
+
+/**
+ * aa_unpack_profile - unpack a serialized profile
+ * @e: serialized data extent information
+ * @error: error code returned if unpacking fails
+ */
+static struct aa_profile *aa_unpack_profile(struct aa_ext *e, int depth)
+{
+	struct aa_profile *profile = NULL;
+
+	int error = -EPROTO;
+
+	profile = alloc_aa_profile();
+	if (!profile)
+		return ERR_PTR(-ENOMEM);
+
+	/* check that we have the right struct being passed */
+	if (!aa_is_nameX(e, AA_STRUCT, "profile"))
+		goto fail;
+	if (!aa_is_dynstring(e, &profile->name, NULL))
+		goto fail;
+
+	/* per profile debug flags (complain, audit) */
+	if (!aa_is_nameX(e, AA_STRUCT, "flags"))
+		goto fail;
+	if (!aa_is_u32(e, NULL, NULL))
+		goto fail;
+	if (!aa_is_u32(e, &(profile->flags.complain), NULL))
+		goto fail;
+	if (!aa_is_u32(e, &(profile->flags.audit), NULL))
+		goto fail;
+	if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+		goto fail;
+
+	if (!aa_is_u32(e, &(profile->capabilities), NULL))
+		goto fail;
+
+	/* get file rules */
+	profile->file_rules = aa_unpack_dfa(e);
+	if (IS_ERR(profile->file_rules)) {
+		error = PTR_ERR(profile->file_rules);
+		profile->file_rules = NULL;
+		goto fail;
+	}
+
+	/* get optional subprofiles */
+	if (aa_is_nameX(e, AA_LIST, "hats")) {
+		if (depth > 0)
+			goto fail;
+		while (!aa_is_nameX(e, AA_LISTEND, NULL)) {
+			struct aa_profile *subprofile;
+			subprofile = aa_unpack_profile(e, depth + 1);
+			if (IS_ERR(subprofile)) {
+				error = PTR_ERR(subprofile);
+				goto fail;
+			}
+			subprofile->parent = profile;
+			list_add(&subprofile->list, &profile->sub);
+		}
+	}
+
+	if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+		goto fail;
+
+	return profile;
+
+fail:
+	aa_audit_message(NULL, GFP_KERNEL, "Invalid profile %s",
+			 profile && profile->name ? profile->name : "unknown");
+
+	if (profile)
+		free_aa_profile(profile);
+
+	return ERR_PTR(error);
+}
+
+/**
+ * aa_unpack_profile_wrapper - unpack a serialized base profile
+ * @e: serialized data extent information
+ *
+ * check interface version unpack a profile and all its hats and patch
+ * in any extra information that the profile needs.
+ */
+static struct aa_profile *aa_unpack_profile_wrapper(struct aa_ext *e)
+{
+	struct aa_profile *profile = aa_unpack_profile(e, 0);
+	if (!IS_ERR(profile) &&
+	    (!list_empty(&profile->sub) || profile->flags.complain)) {
+		int error;
+		if ((error = attach_nullprofile(profile))) {
+			aa_put_profile(profile);
+			return ERR_PTR(error);
+		}
+	}
+
+	return profile;
+}
+
+/**
+ * aa_verify_head - unpack serialized stream header
+ * @e: serialized data read head
+ *
+ * returns error or 0 if header is good
+ */
+static int aa_verify_header(struct aa_ext *e)
+{
+	/* get the interface version */
+	if (!aa_is_u32(e, &e->version, "version")) {
+		aa_audit_message(NULL, GFP_KERNEL, "Interface version missing");
+		return -EPROTONOSUPPORT;
+	}
+
+	/* check that the interface version is currently supported */
+	if (e->version != 3) {
+		aa_audit_message(NULL, GFP_KERNEL, "Unsupported interface "
+				 "version (%d)", e->version);
+		return -EPROTONOSUPPORT;
+	}
+	return 0;
+}
+
+/**
+ * aa_add_profile - Unpack and add a new profile to the profile list
+ * @data: serialized data stream
+ * @size: size of the serialized data stream
+ */
+ssize_t aa_add_profile(void *data, size_t size)
+{
+	struct aa_profile *profile = NULL;
+	struct aa_ext e = {
+		.start = data,
+		.end = data + size,
+		.pos = data
+	};
+	ssize_t error = aa_verify_header(&e);
+	if (error)
+		return error;
+
+	profile = aa_unpack_profile_wrapper(&e);
+	if (IS_ERR(profile))
+		return PTR_ERR(profile);
+
+	mutex_lock(&aa_interface_lock);
+	write_lock(&profile_list_lock);
+	if (__aa_find_profile(profile->name, &profile_list)) {
+		/* A profile with this name exists already. */
+		write_unlock(&profile_list_lock);
+		mutex_unlock(&aa_interface_lock);
+		aa_put_profile(profile);
+		return -EEXIST;
+	}
+	list_add(&profile->list, &profile_list);
+	write_unlock(&profile_list_lock);
+	mutex_unlock(&aa_interface_lock);
+
+	return size;
+}
+
+/**
+ * task_replace - replace a task's profile
+ * @task: task to replace profile on
+ * @new_cxt: new aa_task_context to do replacement with
+ * @new_profile: new profile
+ */
+static inline void task_replace(struct task_struct *task,
+				struct aa_task_context *new_cxt,
+				struct aa_profile *new_profile)
+{
+	struct aa_task_context *cxt = aa_task_context(task);
+
+	AA_DEBUG("%s: replacing profile for task %d "
+		 "profile=%s (%p) hat=%s (%p)\n",
+		 __FUNCTION__,
+		 cxt->task->pid,
+		 cxt->profile->parent->name, cxt->profile->parent,
+		 cxt->profile->name, cxt->profile);
+
+	if (cxt->profile != cxt->profile->parent) {
+		struct aa_profile *hat;
+
+		/*
+		 * The old profile was in a hat, check to see if the new
+		 * profile has an equivalent hat.
+		 */
+		hat = __aa_find_profile(cxt->profile->name, &new_profile->sub);
+
+		if (!hat)
+			hat = aa_dup_profile(new_profile->null_profile);
+
+		aa_change_task_context(task, new_cxt, hat, cxt->hat_magic);
+		aa_put_profile(hat);
+	} else
+		aa_change_task_context(task, new_cxt, new_profile,
+				       cxt->hat_magic);
+}
+
+/**
+ * aa_replace_profile - replace a profile on the profile list
+ * @udata: serialized data stream
+ * @size: size of the serialized data stream
+ *
+ * unpack and replace a profile on the profile list and uses of that profile
+ * by any aa_task_context.  If the profile does not exist on the profile list
+ * it is added.  Return %0 or error.
+ */
+ssize_t aa_replace_profile(void *udata, size_t size)
+{
+	struct aa_profile *old_profile, *new_profile;
+	struct aa_task_context *new_cxt;
+	struct aa_ext e = {
+		.start = udata,
+		.end = udata + size,
+		.pos = udata
+	};
+	ssize_t error = aa_verify_header(&e);
+	if (error)
+		return error;
+
+	new_profile = aa_unpack_profile_wrapper(&e);
+	if (IS_ERR(new_profile))
+		return PTR_ERR(new_profile);
+
+	mutex_lock(&aa_interface_lock);
+	write_lock(&profile_list_lock);
+	old_profile = __aa_find_profile(new_profile->name, &profile_list);
+	if (old_profile) {
+		lock_profile(old_profile);
+		old_profile->isstale = 1;
+		unlock_profile(old_profile);
+		list_del_init(&old_profile->list);
+	}
+	list_add(&new_profile->list, &profile_list);
+	write_unlock(&profile_list_lock);
+
+	if (!old_profile)
+		goto out;
+
+	/*
+	 * Replacement needs to allocate a new aa_task_context for each
+	 * task confined by old_profile.  To do this the profile locks
+	 * are only held when the actual switch is done per task.  While
+	 * looping to allocate a new aa_task_context the old_task list
+	 * may get shorter if tasks exit/change their profile but will
+	 * not get longer as new task will not use old_profile detecting
+	 * that is stale.
+	 */
+	do {
+		new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
+
+		lock_both_profiles(old_profile, new_profile);
+		if (!list_empty(&old_profile->task_contexts)) {
+			struct task_struct *task =
+				list_entry(old_profile->task_contexts.next,
+					   struct aa_task_context, list)->task;
+			task_lock(task);
+			task_replace(task, new_cxt, new_profile);
+			task_unlock(task);
+			new_cxt = NULL;
+		}
+		unlock_both_profiles(old_profile, new_profile);
+	} while (!new_cxt);
+	aa_free_task_context(new_cxt);
+	aa_put_profile(old_profile);
+
+out:
+	mutex_unlock(&aa_interface_lock);
+	return size;
+}
+
+/**
+ * aa_remove_profile - remove a profile from the system
+ * @name: name of the profile to remove
+ * @size: size of the name
+ *
+ * remove a profile from the profile list and all aa_task_context references
+ * to said profile.
+ */
+ssize_t aa_remove_profile(const char *name, size_t size)
+{
+	struct aa_profile *profile;
+
+	mutex_lock(&aa_interface_lock);
+	write_lock(&profile_list_lock);
+	profile = __aa_find_profile(name, &profile_list);
+	if (!profile) {
+		write_unlock(&profile_list_lock);
+		mutex_unlock(&aa_interface_lock);
+		return -ENOENT;
+	}
+
+	/* Remove the profile from each task context it is on. */
+	lock_profile(profile);
+	profile->isstale = 1;
+	aa_unconfine_tasks(profile);
+	unlock_profile(profile);
+
+	/* Release the profile itself. */
+	list_del_init(&profile->list);
+	aa_put_profile(profile);
+	write_unlock(&profile_list_lock);
+	mutex_unlock(&aa_interface_lock);
+
+	return size;
+}
+
+/**
+ * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
+ * @kr: kref callback for freeing of a profile
+ */
+void free_aa_profile_kref(struct kref *kref)
+{
+	struct aa_profile *p=container_of(kref, struct aa_profile, count);
+
+	free_aa_profile(p);
+}
+
+/**
+ * alloc_aa_profile - allocate, initialize and return a new profile
+ * Returns NULL on failure.
+ */
+struct aa_profile *alloc_aa_profile(void)
+{
+	struct aa_profile *profile;
+
+	profile = kzalloc(sizeof(*profile), GFP_KERNEL);
+	AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
+	if (profile) {
+		profile->parent = profile;
+		INIT_LIST_HEAD(&profile->list);
+		INIT_LIST_HEAD(&profile->sub);
+		kref_init(&profile->count);
+		INIT_LIST_HEAD(&profile->task_contexts);
+		spin_lock_init(&profile->lock);
+	}
+	return profile;
+}
+
+/**
+ * free_aa_profile - free a profile
+ * @profile: the profile to free
+ *
+ * Free a profile, its hats and null_profile. All references to the profile,
+ * its hats and null_profile must have been put.
+ *
+ * If the profile was referenced from a task context, free_aa_profile() will
+ * be called from an rcu callback routine, so we must not sleep here.
+ */
+void free_aa_profile(struct aa_profile *profile)
+{
+	struct aa_profile *p, *ptmp;
+
+	AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
+
+	if (!profile)
+		return;
+
+	/* profile is still on global profile list -- invalid */
+	if (!list_empty(&profile->list)) {
+		AA_ERROR("%s: internal error, "
+			 "profile '%s' still on global list\n",
+			 __FUNCTION__,
+			 profile->name);
+		BUG();
+	}
+
+	aa_match_free(profile->file_rules);
+
+	/*
+	 * Use free_aa_profile instead of aa_put_profile to destroy the
+	 * null_profile, because the null_profile use the same reference
+	 * counting as hats, ie. the count goes to the base profile.
+	 */
+	free_aa_profile(profile->null_profile);
+	list_for_each_entry_safe(p, ptmp, &profile->sub, list) {
+		list_del_init(&p->list);
+		p->parent = p;
+		aa_put_profile(p);
+	}
+
+	if (profile->name) {
+		AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
+		kfree(profile->name);
+	}
+
+	kfree(profile);
+}
+
+/**
+ * aa_unconfine_tasks - remove tasks on a profile's task context list
+ * @profile: profile to remove tasks from
+ *
+ * Assumes that @profile lock is held.
+ */
+void aa_unconfine_tasks(struct aa_profile *profile)
+{
+	while (!list_empty(&profile->task_contexts)) {
+		struct task_struct *task =
+			list_entry(profile->task_contexts.next,
+				   struct aa_task_context, list)->task;
+		task_lock(task);
+		aa_change_task_context(task, NULL, NULL, 0);
+		task_unlock(task);
+	}
+}

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 40/45] AppArmor: all the rest
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (38 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 41/45] Add AppArmor LSM to security/Makefile jjohansen
                   ` (5 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, John Johansen, Andreas Gruenbacher

[-- Attachment #1: apparmor-misc.diff --]
[-- Type: text/plain, Size: 30861 bytes --]

All the things that didn't nicely fit in a category on their own: kbuild
code, declararions and inline functions, /sys/kernel/security/apparmor
filesystem for controlling apparmor from user space, profile list
functions, locking documentation, /proc/$pid/task/$tid/attr/current
access.

Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 security/apparmor/Kconfig      |    9 +
 security/apparmor/Makefile     |   13 ++
 security/apparmor/apparmor.h   |  259 +++++++++++++++++++++++++++++++++++++++++
 security/apparmor/apparmorfs.c |  250 +++++++++++++++++++++++++++++++++++++++
 security/apparmor/inline.h     |  219 ++++++++++++++++++++++++++++++++++
 security/apparmor/list.c       |   94 ++++++++++++++
 security/apparmor/locking.txt  |   59 +++++++++
 security/apparmor/procattr.c   |  138 +++++++++++++++++++++
 8 files changed, 1041 insertions(+)

--- /dev/null
+++ b/security/apparmor/Kconfig
@@ -0,0 +1,9 @@
+config SECURITY_APPARMOR
+	tristate "AppArmor support"
+	depends on SECURITY!=n
+	help
+	  This enables the AppArmor security module.
+	  Required userspace tools (if they are not included in your
+	  distribution) and further information may be found at
+	  <http://forge.novell.com/modules/xfmod/project/?apparmor>
+	  If you are unsure how to answer this question, answer N.
--- /dev/null
+++ b/security/apparmor/Makefile
@@ -0,0 +1,13 @@
+# Makefile for AppArmor Linux Security Module
+#
+obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
+
+apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o \
+	      module_interface.o match.o
+
+quiet_cmd_make-caps = GEN     $@
+cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z > $@
+
+$(obj)/main.o : $(obj)/capability_names.h
+$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
+	$(call cmd,make-caps)
--- /dev/null
+++ b/security/apparmor/apparmor.h
@@ -0,0 +1,259 @@
+/*
+ *	Copyright (C) 1998-2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor internal prototypes
+ */
+
+#ifndef __APPARMOR_H
+#define __APPARMOR_H
+
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/binfmts.h>
+#include <linux/rcupdate.h>
+
+/*
+ * We use MAY_READ, MAY_WRITE, MAY_EXEC, and the following flags for
+ * profile permissions (we don't use MAY_APPEND):
+ */
+#define AA_MAY_LINK			0x0010
+#define AA_EXEC_INHERIT			0x0020
+#define AA_EXEC_UNCONFINED		0x0040
+#define AA_EXEC_PROFILE			0x0080
+#define AA_EXEC_MMAP			0x0100
+#define AA_EXEC_UNSAFE			0x0200
+
+#define AA_EXEC_MODIFIERS		(AA_EXEC_INHERIT | \
+					 AA_EXEC_UNCONFINED | \
+					 AA_EXEC_PROFILE)
+
+#define AA_SECURE_EXEC_NEEDED		1
+
+/* Control parameters (0 or 1), settable thru module/boot flags or
+ * via /sys/kernel/security/apparmor/control */
+extern int apparmor_complain;
+extern int apparmor_debug;
+extern int apparmor_audit;
+extern int apparmor_logsyscall;
+extern unsigned int apparmor_path_max;
+
+#define PROFILE_COMPLAIN(_profile) \
+	(apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
+
+#define APPARMOR_COMPLAIN(_cxt) \
+	(apparmor_complain == 1 || \
+	 ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain))
+
+#define PROFILE_AUDIT(_profile) \
+	(apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
+
+#define APPARMOR_AUDIT(_cxt) \
+	(apparmor_audit == 1 || \
+	 ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit))
+
+/*
+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
+ * which is not related to profile accesses.
+ */
+
+#define AA_DEBUG(fmt, args...)						\
+	do {								\
+		if (apparmor_debug)					\
+			printk(KERN_DEBUG "AppArmor: " fmt, ##args);	\
+	} while (0)
+
+#define AA_ERROR(fmt, args...)	printk(KERN_ERR "AppArmor: " fmt, ##args)
+
+/* struct aa_profile - basic confinement data
+ * @parent: non refcounted pointer to parent profile
+ * @name: the profiles name
+ * @file_rules: dfa containing the profiles file rules
+ * @list: list this profile is on
+ * @sub: profiles list of subprofiles (HATS)
+ * @flags: flags controlling profile behavior
+ * @null_profile: if needed per profile learning and null confinement profile
+ * @isstale: flag indicating if profile is stale
+ * @capabilities: capabilities granted by the process
+ * @count: reference count of the profile
+ *
+ * The AppArmor profile contains the basic confinement data.  Each profile
+ * has a name and potentially a list of sub profile entries. All non stale
+ * profiles are on the profile_list.
+ *
+ * The task_contexts list and the isstale flag are protected by the
+ * profile lock.
+ *
+ * If a task context is moved between two profiles, we first need to grab
+ * both profile locks. lock_both_profiles() does that in a deadlock-safe
+ * way.
+ */
+struct aa_profile {
+	struct aa_profile *parent;
+	char *name;
+	struct aa_dfa *file_rules;
+	struct list_head list;
+	struct list_head sub;
+	struct {
+		int complain;
+		int audit;
+	} flags;
+	struct aa_profile *null_profile;
+	int isstale;
+
+	kernel_cap_t capabilities;
+	struct kref count;
+	struct list_head task_contexts;
+	spinlock_t lock;
+	unsigned long int_flags;
+};
+
+extern struct list_head profile_list;
+extern rwlock_t profile_list_lock;
+extern struct mutex aa_interface_lock;
+
+/**
+ * struct aa_task_context - primary label for confined tasks
+ * @profile: the current profile
+ * @hat_magic: the magic token controling the ability to leave a hat
+ * @list: list this aa_task_context is on
+ * @task: task that the aa_task_context confines
+ * @rcu: rcu head used when freeing the aa_task_context
+ * @caps_logged: caps that have previously generated log entries
+ *
+ * Contains the task's current profile (which could change due to
+ * change_hat).  Plus the hat_magic needed during change_hat.
+ */
+struct aa_task_context {
+	struct aa_profile *profile;	/* The current profile */
+	u64 hat_magic;			/* used with change_hat */
+	struct list_head list;
+	struct task_struct *task;
+	struct rcu_head rcu;
+	kernel_cap_t caps_logged;
+};
+
+extern struct aa_profile *null_complain_profile;
+
+/* aa_audit - AppArmor auditing structure
+ * Structure is populated by access control code and passed to aa_audit which
+ * provides for a single point of logging.
+ */
+
+struct aa_audit {
+	unsigned short type, flags;
+	unsigned int result;
+	gfp_t gfp_mask;
+	int error_code;
+	const char *name;
+	char *buffer;
+	union {
+		int mask;
+		int capability;
+		struct {
+			const char *name2;
+			char *buffer2;
+		};
+		struct iattr *iattr;
+		va_list vaval;
+	};
+};
+
+/* audit types */
+#define AA_MANGLE_NAME		32
+#define AA_MANGLE_NAME2		64
+#define AA_AUDITTYPE_FILE	(1 | AA_MANGLE_NAME)
+#define AA_AUDITTYPE_DIR	(2 | AA_MANGLE_NAME)
+#define AA_AUDITTYPE_ATTR	(3 | AA_MANGLE_NAME)
+#define AA_AUDITTYPE_XATTR	(4 | AA_MANGLE_NAME)
+#define AA_AUDITTYPE_LINK	(5 | AA_MANGLE_NAME | AA_MANGLE_NAME2)
+#define AA_AUDITTYPE_CAP	6
+#define AA_AUDITTYPE_MSG	7
+#define AA_AUDITTYPE_SYSCALL	8
+
+/* audit flags */
+#define AA_AUDITFLAG_AUDITSS_SYSCALL 1 /* log syscall context */
+#define AA_AUDITFLAG_LOGERR	     2 /* log operations that failed due to
+					   non permission errors  */
+
+/* Flags for the permission check functions */
+#define AA_CHECK_FD	1  /* coming from a file descriptor */
+#define AA_CHECK_DIR	2  /* file type is directory */
+#define AA_CHECK_MANGLE	4  /* leave extra room for name mangling */
+
+/* main.c */
+extern int alloc_null_complain_profile(void);
+extern void free_null_complain_profile(void);
+extern int attach_nullprofile(struct aa_profile *profile);
+extern int aa_audit_message(struct aa_profile *profile, gfp_t gfp,
+			    const char *, ...)
+	__attribute__ ((format (printf, 3, 4)));
+extern int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
+				  const char *);
+extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
+
+extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
+		   struct vfsmount *mnt, struct iattr *iattr);
+extern int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
+			 struct vfsmount *mnt, const char *operation, int mask,
+			 int check);
+extern int aa_capability(struct aa_task_context *cxt, int cap);
+extern int aa_perm(struct aa_profile *profile, struct dentry *dentry,
+		   struct vfsmount *mnt, int mask, int check);
+extern int aa_perm_dir(struct aa_profile *profile, struct dentry *dentry,
+		       struct vfsmount *mnt, const char *operation, int mask);
+extern int aa_perm_path(struct aa_profile *, const char *, int);
+extern int aa_link(struct aa_profile *profile,
+		   struct dentry *link, struct vfsmount *link_mnt,
+		   struct dentry *target, struct vfsmount *target_mnt);
+extern int aa_clone(struct task_struct *task);
+extern int aa_register(struct linux_binprm *bprm);
+extern void aa_release(struct task_struct *task);
+extern int aa_change_hat(const char *id, u64 hat_magic);
+extern struct aa_profile *__aa_find_profile(const char *name,
+					    struct list_head *list);
+extern struct aa_profile *__aa_replace_profile(struct task_struct *task,
+					       struct aa_profile *profile,
+					       u32 hat_magic);
+extern struct aa_task_context *lock_task_and_profiles(struct task_struct *task,
+						      struct aa_profile *profile);
+extern void aa_change_task_context(struct task_struct *task,
+				   struct aa_task_context *new_cxt,
+				   struct aa_profile *profile, u64 hat_magic);
+extern int aa_may_ptrace(struct aa_task_context *cxt,
+			 struct aa_profile *tracee);
+
+/* list.c */
+extern void aa_profilelist_release(void);
+
+/* module_interface.c */
+extern ssize_t aa_add_profile(void *, size_t);
+extern ssize_t aa_replace_profile(void *, size_t);
+extern ssize_t aa_remove_profile(const char *, size_t);
+extern struct aa_profile *alloc_aa_profile(void);
+extern void free_aa_profile(struct aa_profile *profile);
+extern void free_aa_profile_kref(struct kref *kref);
+extern void aa_unconfine_tasks(struct aa_profile *profile);
+
+/* procattr.c */
+extern int aa_getprocattr(struct aa_profile *profile, char **string,
+			  unsigned *len);
+extern int aa_setprocattr_changehat(char *args);
+extern int aa_setprocattr_setprofile(struct task_struct *task, char *args);
+
+/* apparmorfs.c */
+extern int create_apparmorfs(void);
+extern void destroy_apparmorfs(void);
+
+/* match.c */
+extern struct aa_dfa *aa_match_alloc(void);
+extern void aa_match_free(struct aa_dfa *dfa);
+extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
+extern int verify_dfa(struct aa_dfa *dfa);
+extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str);
+
+#endif  /* __APPARMOR_H */
--- /dev/null
+++ b/security/apparmor/apparmorfs.c
@@ -0,0 +1,250 @@
+/*
+ *	Copyright (C) 1998-2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor filesystem (part of securityfs)
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+
+#include "apparmor.h"
+#include "inline.h"
+
+static char *aa_simple_write_to_buffer(const char __user *userbuf,
+				       size_t alloc_size, size_t copy_size,
+				       loff_t *pos, const char *msg)
+{
+	struct aa_profile *profile;
+	char *data;
+
+	if (*pos != 0) {
+		/* only writes from pos 0, that is complete writes */
+		data = ERR_PTR(-ESPIPE);
+		goto out;
+	}
+
+	/*
+	 * Don't allow confined processes to load/replace/remove profiles.
+	 * No sane person would add rules allowing this to a profile
+	 * but we enforce the restriction anyways.
+	 */
+	profile = aa_get_profile(current);
+	if (profile) {
+		aa_audit_message(NULL, GFP_KERNEL, "REJECTING access to "
+				 "profile %s (%d profile %s active %s)",
+				 msg, current->pid, profile->parent->name,
+				 profile->name);
+		aa_put_profile(profile);
+
+		data = ERR_PTR(-EPERM);
+		goto out;
+	}
+
+	data = vmalloc(alloc_size);
+	if (data == NULL) {
+		data = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	if (copy_from_user(data, userbuf, copy_size)) {
+		vfree(data);
+		data = ERR_PTR(-EFAULT);
+		goto out;
+	}
+
+out:
+	return data;
+}
+
+/* apparmor/profiles */
+extern struct seq_operations apparmorfs_profiles_op;
+
+static int aa_profiles_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &apparmorfs_profiles_op);
+}
+
+
+static int aa_profiles_release(struct inode *inode, struct file *file)
+{
+	return seq_release(inode, file);
+}
+
+static struct file_operations apparmorfs_profiles_fops = {
+	.open =		aa_profiles_open,
+	.read =		seq_read,
+	.llseek =	seq_lseek,
+	.release =	aa_profiles_release,
+};
+
+/* apparmor/matching */
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+			       size_t size, loff_t *ppos)
+{
+	const char *matching = "pattern=aadfa";
+
+	return simple_read_from_buffer(buf, size, ppos, matching,
+				       strlen(matching));
+}
+
+static struct file_operations apparmorfs_matching_fops = {
+	.read = 	aa_matching_read,
+};
+
+/* apparmor/.load */
+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
+			       size_t size, loff_t *pos)
+{
+	char *data;
+	ssize_t error;
+
+	data = aa_simple_write_to_buffer(buf, size, size, pos, "load");
+
+	error = PTR_ERR(data);
+	if (!IS_ERR(data)) {
+		error = aa_add_profile(data, size);
+		vfree(data);
+	}
+
+	return error;
+}
+
+
+static struct file_operations apparmorfs_profile_load = {
+	.write = aa_profile_load
+};
+
+/* apparmor/.replace */
+static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
+				  size_t size, loff_t *pos)
+{
+	char *data;
+	ssize_t error;
+
+	data = aa_simple_write_to_buffer(buf, size, size, pos, "replacement");
+
+	error = PTR_ERR(data);
+	if (!IS_ERR(data)) {
+		error = aa_replace_profile(data, size);
+		vfree(data);
+	}
+
+	return error;
+}
+
+
+static struct file_operations apparmorfs_profile_replace = {
+	.write = aa_profile_replace
+};
+
+/* apparmor/.remove */
+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
+				  size_t size, loff_t *pos)
+{
+	char *data;
+	ssize_t error;
+
+	/*
+	 * aa_remove_profile needs a null terminated string so 1 extra
+	 * byte is allocated and the copied data is null terminated.
+	 */
+	data = aa_simple_write_to_buffer(buf, size + 1, size, pos, "removal");
+
+	error = PTR_ERR(data);
+	if (!IS_ERR(data)) {
+		data[size] = 0;
+		error = aa_remove_profile(data, size);
+		vfree(data);
+	}
+
+	return error;
+}
+
+static struct file_operations apparmorfs_profile_remove = {
+	.write = aa_profile_remove
+};
+
+static struct dentry *apparmor_dentry;
+
+static void aafs_remove(const char *name)
+{
+	struct dentry *dentry;
+
+	dentry = lookup_one_len(name, apparmor_dentry, strlen(name));
+	if (!IS_ERR(dentry)) {
+		securityfs_remove(dentry);
+		dput(dentry);
+	}
+}
+
+static int aafs_create(const char *name, int mask, struct file_operations *fops)
+{
+	struct dentry *dentry;
+
+	dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry,
+					NULL, fops);
+
+	return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
+}
+
+void destroy_apparmorfs(void)
+{
+	if (apparmor_dentry) {
+		aafs_remove(".remove");
+		aafs_remove(".replace");
+		aafs_remove(".load");
+		aafs_remove("matching");
+		aafs_remove("profiles");
+		securityfs_remove(apparmor_dentry);
+		apparmor_dentry = NULL;
+	}
+}
+
+int create_apparmorfs(void)
+{
+	int error;
+
+	if (apparmor_dentry) {
+		AA_ERROR("%s: AppArmor securityfs already exists\n",
+			__FUNCTION__);
+		return -EEXIST;
+	}
+
+	apparmor_dentry = securityfs_create_dir("apparmor", NULL);
+	if (IS_ERR(apparmor_dentry)) {
+		error = PTR_ERR(apparmor_dentry);
+		apparmor_dentry = NULL;
+ 		goto error;
+	}
+	error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
+	if (error)
+		goto error;
+	error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
+	if (error)
+		goto error;
+	error = aafs_create(".load", 0640, &apparmorfs_profile_load);
+	if (error)
+		goto error;
+	error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
+	if (error)
+		goto error;
+	error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
+	if (error)
+		goto error;
+
+	return 0;
+
+error:
+	destroy_apparmorfs();
+	AA_ERROR("Error creating AppArmor securityfs\n");
+	return error;
+}
+
--- /dev/null
+++ b/security/apparmor/inline.h
@@ -0,0 +1,219 @@
+/*
+ *	Copyright (C) 1998-2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ */
+
+#ifndef __INLINE_H
+#define __INLINE_H
+
+#include <linux/sched.h>
+
+static inline int mediated_filesystem(struct inode *inode)
+{
+	return !(inode->i_sb->s_flags & MS_NOUSER);
+}
+
+static inline struct aa_task_context *aa_task_context(struct task_struct *task)
+{
+	return rcu_dereference((struct aa_task_context *)task->security);
+}
+
+/**
+ * aa_dup_profile - increment refcount on profile @p
+ * @p: profile
+ */
+static inline struct aa_profile *aa_dup_profile(struct aa_profile *p)
+{
+	if (p)
+		kref_get(&(p->parent->count));
+
+	return p;
+}
+
+/**
+ * aa_put_profile - decrement refcount on profile @p
+ * @p: profile
+ */
+static inline void aa_put_profile(struct aa_profile *p)
+{
+	if (p)
+		kref_put(&p->parent->count, free_aa_profile_kref);
+}
+
+static inline struct aa_profile *aa_get_profile(struct task_struct *task)
+{
+	struct aa_task_context *cxt;
+	struct aa_profile *profile = NULL;
+
+	rcu_read_lock();
+	cxt = aa_task_context(task);
+	if (cxt) {
+		profile = cxt->profile;
+		aa_dup_profile(profile);
+	}
+	rcu_read_unlock();
+
+	return profile;
+}
+
+static inline struct aa_profile *aa_find_profile(const char *name)
+{
+	struct aa_profile *profile = NULL;
+
+	read_lock(&profile_list_lock);
+	profile = aa_dup_profile(__aa_find_profile(name, &profile_list));
+	read_unlock(&profile_list_lock);
+
+	return profile;
+}
+
+static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags)
+{
+	struct aa_task_context *cxt;
+
+	cxt = kzalloc(sizeof(*cxt), flags);
+	if (cxt) {
+		INIT_LIST_HEAD(&cxt->list);
+		INIT_RCU_HEAD(&cxt->rcu);
+	}
+
+	return cxt;
+}
+
+static inline void aa_free_task_context(struct aa_task_context *cxt)
+{
+	if (cxt) {
+		aa_put_profile(cxt->profile);
+		kfree(cxt);
+	}
+}
+
+/**
+ * lock_profile - lock a profile
+ * @profile: the profile to lock
+ *
+ * While the profile is locked, local interrupts are disabled. This also
+ * gives us RCU reader safety.
+ */
+static inline void lock_profile(struct aa_profile *profile)
+{
+	/* We always lock top-level profiles instead of children. */
+	if (profile)
+		profile = profile->parent;
+
+	/*
+	 * Lock the profile.
+	 *
+	 * Need to disable interrupts here because this lock is used in
+	 * the task_free_security hook, which may run in RCU context.
+	 */
+	if (profile)
+		spin_lock_irqsave(&profile->lock, profile->int_flags);
+}
+
+/**
+ * unlock_profile - unlock a profile
+ * @profile: the profile to unlock
+ */
+static inline void unlock_profile(struct aa_profile *profile)
+{
+	/* We always lock top-level profiles instead of children. */
+	if (profile)
+		profile = profile->parent;
+
+	/* Unlock the profile. */
+	if (profile)
+		spin_unlock_irqrestore(&profile->lock, profile->int_flags);
+}
+
+/**
+ * lock_both_profiles  -  lock two profiles in a deadlock-free way
+ * @profile1:	profile to lock (may be NULL)
+ * @profile2:	profile to lock (may be NULL)
+ *
+ * The order in which profiles are passed into lock_both_profiles() /
+ * unlock_both_profiles() does not matter.
+ * While the profile is locked, local interrupts are disabled. This also
+ * gives us RCU reader safety.
+ */
+static inline void lock_both_profiles(struct aa_profile *profile1,
+				      struct aa_profile *profile2)
+{
+	/* We always lock top-level profiles instead of children. */
+	if (profile1)
+		profile1 = profile1->parent;
+	if (profile2)
+		profile2 = profile2->parent;
+
+	/*
+	 * Lock the two profiles.
+	 *
+	 * We need to disable interrupts because the profile locks are
+	 * used in the task_free_security hook, which may run in RCU
+	 * context.
+	 *
+	 * Do not nest spin_lock_irqsave()/spin_unlock_irqresore():
+	 * interrupts only need to be turned off once.
+	 */
+	if (!profile1 || profile1 == profile2) {
+		if (profile2)
+			spin_lock_irqsave(&profile2->lock, profile2->int_flags);
+	} else if (profile1 > profile2) {
+		/* profile1 cannot be NULL here. */
+		spin_lock_irqsave(&profile1->lock, profile1->int_flags);
+		if (profile2)
+			spin_lock(&profile2->lock);
+
+	} else {
+		/* profile2 cannot be NULL here. */
+		spin_lock_irqsave(&profile2->lock, profile2->int_flags);
+		spin_lock(&profile1->lock);
+	}
+}
+
+/**
+ * unlock_both_profiles  -  unlock two profiles in a deadlock-free way
+ * @profile1:	profile to unlock (may be NULL)
+ * @profile2:	profile to unlock (may be NULL)
+ *
+ * The order in which profiles are passed into lock_both_profiles() /
+ * unlock_both_profiles() does not matter.
+ * While the profile is locked, local interrupts are disabled. This also
+ * gives us RCU reader safety.
+ */
+static inline void unlock_both_profiles(struct aa_profile *profile1,
+				        struct aa_profile *profile2)
+{
+	/* We always lock top-level profiles instead of children. */
+	if (profile1)
+		profile1 = profile1->parent;
+	if (profile2)
+		profile2 = profile2->parent;
+
+	/* Unlock the two profiles. */
+	if (!profile1 || profile1 == profile2) {
+		if (profile2)
+			spin_unlock_irqrestore(&profile2->lock,
+					       profile2->int_flags);
+	} else if (profile1 > profile2) {
+		/* profile1 cannot be NULL here. */
+		if (profile2)
+			spin_unlock(&profile2->lock);
+		spin_unlock_irqrestore(&profile1->lock, profile1->int_flags);
+	} else {
+		/* profile2 cannot be NULL here. */
+		spin_unlock(&profile1->lock);
+		spin_unlock_irqrestore(&profile2->lock, profile2->int_flags);
+	}
+}
+
+static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname)
+{
+	        return dfa ? aa_dfa_match(dfa, pathname) : 0;
+}
+
+#endif /* __INLINE_H__ */
--- /dev/null
+++ b/security/apparmor/list.c
@@ -0,0 +1,94 @@
+/*
+ *	Copyright (C) 1998-2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor Profile List Management
+ */
+
+#include <linux/seq_file.h>
+#include "apparmor.h"
+#include "inline.h"
+
+/* list of all profiles and lock */
+LIST_HEAD(profile_list);
+rwlock_t profile_list_lock = RW_LOCK_UNLOCKED;
+
+/**
+ * __aa_find_profile  -  look up a profile on the profile list
+ * @name: name of profile to find
+ * @head: list to search
+ *
+ * Returns a pointer to the profile on the list, or NULL if no profile
+ * called @name exists. The caller must hold the profile_list_lock.
+ */
+struct aa_profile *__aa_find_profile(const char *name, struct list_head *head)
+{
+	struct aa_profile *profile;
+
+	list_for_each_entry(profile, head, list) {
+		if (!strcmp(profile->name, name))
+			return profile;
+	}
+
+	return NULL;
+}
+
+/**
+ * aa_profilelist_release - Remove all profiles from profile_list
+ */
+void aa_profilelist_release(void)
+{
+	struct aa_profile *p, *tmp;
+
+	write_lock(&profile_list_lock);
+	list_for_each_entry_safe(p, tmp, &profile_list, list) {
+		list_del_init(&p->list);
+		aa_put_profile(p);
+	}
+	write_unlock(&profile_list_lock);
+}
+
+static void *p_start(struct seq_file *f, loff_t *pos)
+{
+	struct aa_profile *node;
+	loff_t l = *pos;
+
+	read_lock(&profile_list_lock);
+	list_for_each_entry(node, &profile_list, list)
+		if (!l--)
+			return node;
+	return NULL;
+}
+
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
+{
+	struct list_head *lh = ((struct aa_profile *)p)->list.next;
+	(*pos)++;
+	return lh == &profile_list ?
+			NULL : list_entry(lh, struct aa_profile, list);
+}
+
+static void p_stop(struct seq_file *f, void *v)
+{
+	read_unlock(&profile_list_lock);
+}
+
+static int seq_show_profile(struct seq_file *f, void *v)
+{
+	struct aa_profile *profile = (struct aa_profile *)v;
+	seq_printf(f, "%s (%s)\n", profile->name,
+		   PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
+	return 0;
+}
+
+/* Used in apparmorfs.c */
+struct seq_operations apparmorfs_profiles_op = {
+	.start =	p_start,
+	.next =		p_next,
+	.stop =		p_stop,
+	.show =		seq_show_profile,
+};
--- /dev/null
+++ b/security/apparmor/locking.txt
@@ -0,0 +1,59 @@
+Locking in AppArmor
+===================
+
+Lock hierarchy:
+
+	aa_interface_lock
+	  profile_list_lock
+	    aa_profile->lock
+	      task_lock()
+
+
+Which lock protects what?
+
+	/-----------------------+-------------------------------\
+	| Variable		| Lock				|
+	>-----------------------+-------------------------------<
+	| profile_list		| profile_list_lock		|
+	+-----------------------+-------------------------------+
+	| aa_profile		| (reference count)		|
+	+-----------------------+-------------------------------+
+	| aa_profile->		| aa_profile->lock		|
+	|   isstale,		|				|
+	|   task_contexts	|				|
+	+-----------------------+-------------------------------+
+	| task_struct->security	| read: RCU			|
+	|			| write: task_lock()		|
+	+-----------------------+-------------------------------+
+	| aa_profile->sub	| handle on the profile (list	|
+	|			| is never modified)		|
+	\-----------------------+-------------------------------/
+
+(Obviously, the list_heads embedded in data structures are always
+protected with the lock that also protects the list.)
+
+When moving a task context from one profile to another, we grab both
+profile locks with lock_both_profiles(). This ensures that both locks
+are always taken in the same order, and so we won't deadlock.
+
+Since task_struct->security is RCU protected the aa_task_struct it
+references is only guarenteed to exist for the rcu cycle.  Where
+aa_task_context->profile is needed in blocking operations the
+profile's reference count is incremented and the profile reference
+is used.
+
+Profiles on profile_list are never stale: when a profile becomes stale,
+it is removed from profile_list at the same time (under profile_list_lock
+and aa_profile->lock).
+
+The aa_interface_lock is taken whenever user-space modifies the profile
+list, and can sleep. This ensures that profile loading/replacement/removal
+won't race with itself. We release the profile_list_lock as soon as
+possible to avoid stalling exec during profile loading/replacement/removal.
+
+lock_dep reports a false 'possible irq lock inversion dependency detected'
+when the profile lock is taken in aa_release.  This is due to that the
+task_lock is often taken inside the profile lock but other kernel code
+takes the task_lock with interrupts enabled.  A deadlock will not actually
+occur because apparmor does not take the task_lock in hard_irq or soft_irq
+context.
--- /dev/null
+++ b/security/apparmor/procattr.c
@@ -0,0 +1,138 @@
+/*
+ *	Copyright (C) 1998-2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor /proc/pid/attr handling
+ */
+
+#include "apparmor.h"
+#include "inline.h"
+
+int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len)
+{
+	char *str;
+
+	if (profile) {
+		const char *mode_str = PROFILE_COMPLAIN(profile) ?
+			" (complain)" : " (enforce)";
+
+		*len = ((profile != profile->parent) ?
+		           strlen(profile->parent->name) + 1 : 0) +
+		       strlen(mode_str) + strlen(profile->name) + 1;
+		str = kmalloc(*len, GFP_ATOMIC);
+		if (!str)
+			return -ENOMEM;
+
+		if (profile != profile->parent) {
+			memcpy(str, profile->parent->name,
+			       strlen(profile->parent->name));
+			str += strlen(profile->parent->name);
+			*str++ = '^';
+		}
+		memcpy(str, profile->name, strlen(profile->name));
+		str += strlen(profile->name);
+		memcpy(str, mode_str, strlen(mode_str));
+		str += strlen(mode_str);
+		*str++ = '\n';
+		str -= *len;
+	} else {
+		const char *unconfined_str = "unconfined\n";
+
+		*len = strlen(unconfined_str);
+		str = kmalloc(*len, GFP_ATOMIC);
+		if (!str)
+			return -ENOMEM;
+
+		memcpy(str, unconfined_str, *len);
+	}
+	*string = str;
+
+	return 0;
+}
+
+int aa_setprocattr_changehat(char *args)
+{
+	char *hat;
+	u64 magic;
+
+	magic = simple_strtoull(args, &hat, 16);
+	if (hat == args || *hat != '^') {
+		AA_ERROR("change_hat: Invalid input '%s'", args);
+		return -EINVAL;
+	}
+	hat++;  /* skip ^ */
+	if (!*hat)
+		hat = NULL;
+	if (!hat && !magic) {
+		AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
+		return -EINVAL;
+	}
+
+	AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
+		 __FUNCTION__, magic, hat ? hat : NULL);
+
+	return aa_change_hat(hat, magic);
+}
+
+int aa_setprocattr_setprofile(struct task_struct *task, char *args)
+{
+	struct aa_profile *old_profile, *new_profile;
+
+	AA_DEBUG("%s: current %d\n",
+		 __FUNCTION__, current->pid);
+
+repeat:
+	if (strcmp(args, "unconfined") == 0)
+		new_profile = NULL;
+	else {
+		new_profile = aa_find_profile(args);
+		if (!new_profile) {
+			aa_audit_message(NULL, GFP_KERNEL, "Unable to switch "
+					 "task %d to profile '%s'. No such "
+					 "profile.",
+					 task->pid, args);
+
+			return -EINVAL;
+		}
+	}
+
+	old_profile = __aa_replace_profile(task, new_profile, 0);
+	if (IS_ERR(old_profile)) {
+		int error;
+
+		aa_put_profile(new_profile);
+		error = PTR_ERR(old_profile);
+		if (error == -ESTALE)
+			goto repeat;
+		return error;
+	}
+
+	if (new_profile) {
+		aa_audit_message(NULL, GFP_KERNEL, "Switching task %d profile "
+				 "%s active %s to new profile %s",
+				 task->pid, old_profile ?
+				 old_profile->parent->name : "unconfined",
+				 old_profile ? old_profile->name : "unconfined",
+				 args);
+	} else {
+		if (old_profile) {
+			aa_audit_message(NULL, GFP_KERNEL, "Unconfining task "
+					 "%d profile %s active %s",
+					 task->pid, old_profile->parent->name,
+					 old_profile->name);
+		} else {
+			aa_audit_message(NULL, GFP_KERNEL, "task %d is already "
+					 "unconfined",
+					 task->pid);
+		}
+	}
+
+	aa_put_profile(old_profile);
+	aa_put_profile(new_profile);
+
+	return 0;
+}

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 41/45] Add AppArmor LSM to security/Makefile
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (39 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 40/45] AppArmor: all the rest jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 42/45] AppArmor: add lock subtyping so lockdep does not report false dependencies jjohansen
                   ` (4 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, John Johansen, Andreas Gruenbacher

[-- Attachment #1: apparmor-intree.diff --]
[-- Type: text/plain, Size: 1243 bytes --]

Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 security/Kconfig          |    1 +
 security/Makefile         |    1 +
 security/apparmor/Kconfig |    3 ++-
 3 files changed, 4 insertions(+), 1 deletion(-)

--- a/security/Kconfig
+++ b/security/Kconfig
@@ -94,6 +94,7 @@ config SECURITY_ROOTPLUG
 	  If you are unsure how to answer this question, answer N.
 
 source security/selinux/Kconfig
+source security/apparmor/Kconfig
 
 endmenu
 
--- a/security/Makefile
+++ b/security/Makefile
@@ -14,5 +14,6 @@ endif
 obj-$(CONFIG_SECURITY)			+= security.o dummy.o inode.o
 # Must precede capability.o in order to stack properly.
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
+obj-$(CONFIG_SECURITY_APPARMOR)		+= commoncap.o apparmor/
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -1,6 +1,7 @@
 config SECURITY_APPARMOR
 	tristate "AppArmor support"
-	depends on SECURITY!=n
+	depends on SECURITY
+	select AUDIT
 	help
 	  This enables the AppArmor security module.
 	  Required userspace tools (if they are not included in your

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 42/45] AppArmor: add lock subtyping so lockdep does not report false dependencies
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (40 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 41/45] Add AppArmor LSM to security/Makefile jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 43/45] Switch to vfs_permission() in do_path_lookup() jjohansen
                   ` (3 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, linux-fsdevel, John Johansen,
	Andreas Gruenbacher, Ingo Molnar

[-- Attachment #1: apparmor-lockdep.diff --]
[-- Type: text/plain, Size: 5942 bytes --]

AppArmor uses lock subtyping to avoid false positives from lockdep.  The
profile lock is often taken nested, but it is guaranteed to be in a lock
safe order and not the same lock when done, so it is safe.

A third lock type (aa_lock_task_release) is given to the profile lock
when it is taken in soft irq context during task release (aa_release).
This is to avoid a false positive between the task lock and the profile
lock.  In task context the profile lock wraps the task lock with irqs
off, but the kernel takes the task lock with irqs enabled.  This won't
ever result in a deadlock because aa_release doesn't need to take the
task lock of the dead task that is released.

Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Cc: Ingo Molnar <mingo@elte.hu>

---
 security/apparmor/apparmor.h  |    7 +++++++
 security/apparmor/inline.h    |   25 ++++++++++++++++++-------
 security/apparmor/locking.txt |   21 +++++++++++++++------
 security/apparmor/main.c      |    6 +++---
 4 files changed, 43 insertions(+), 16 deletions(-)

--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -185,6 +185,13 @@ struct aa_audit {
 #define AA_CHECK_DIR	2  /* file type is directory */
 #define AA_CHECK_MANGLE	4  /* leave extra room for name mangling */
 
+/* lock subtypes so lockdep does not raise false dependencies */
+enum aa_lock_class {
+	aa_lock_normal,
+	aa_lock_nested,
+	aa_lock_task_release
+};
+
 /* main.c */
 extern int alloc_null_complain_profile(void);
 extern void free_null_complain_profile(void);
--- a/security/apparmor/inline.h
+++ b/security/apparmor/inline.h
@@ -99,7 +99,8 @@ static inline void aa_free_task_context(
  * While the profile is locked, local interrupts are disabled. This also
  * gives us RCU reader safety.
  */
-static inline void lock_profile(struct aa_profile *profile)
+static inline void lock_profile_nested(struct aa_profile *profile,
+				       enum aa_lock_class lock_class)
 {
 	/* We always lock top-level profiles instead of children. */
 	if (profile)
@@ -112,7 +113,13 @@ static inline void lock_profile(struct a
 	 * the task_free_security hook, which may run in RCU context.
 	 */
 	if (profile)
-		spin_lock_irqsave(&profile->lock, profile->int_flags);
+		spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
+					 lock_class);
+}
+
+static inline void lock_profile(struct aa_profile *profile)
+{
+	lock_profile_nested(profile, aa_lock_normal);
 }
 
 /**
@@ -161,17 +168,21 @@ static inline void lock_both_profiles(st
 	 */
 	if (!profile1 || profile1 == profile2) {
 		if (profile2)
-			spin_lock_irqsave(&profile2->lock, profile2->int_flags);
+			spin_lock_irqsave_nested(&profile2->lock,
+						 profile2->int_flags,
+						 aa_lock_normal);
 	} else if (profile1 > profile2) {
 		/* profile1 cannot be NULL here. */
-		spin_lock_irqsave(&profile1->lock, profile1->int_flags);
+		spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
+					 aa_lock_normal);
 		if (profile2)
-			spin_lock(&profile2->lock);
+			spin_lock_nested(&profile2->lock, aa_lock_nested);
 
 	} else {
 		/* profile2 cannot be NULL here. */
-		spin_lock_irqsave(&profile2->lock, profile2->int_flags);
-		spin_lock(&profile1->lock);
+		spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
+					 aa_lock_normal);
+		spin_lock_nested(&profile1->lock, aa_lock_nested);
 	}
 }
 
--- a/security/apparmor/locking.txt
+++ b/security/apparmor/locking.txt
@@ -51,9 +51,18 @@ list, and can sleep. This ensures that p
 won't race with itself. We release the profile_list_lock as soon as
 possible to avoid stalling exec during profile loading/replacement/removal.
 
-lock_dep reports a false 'possible irq lock inversion dependency detected'
-when the profile lock is taken in aa_release.  This is due to that the
-task_lock is often taken inside the profile lock but other kernel code
-takes the task_lock with interrupts enabled.  A deadlock will not actually
-occur because apparmor does not take the task_lock in hard_irq or soft_irq
-context.
+AppArmor uses lock subtyping to avoid false positives from lockdep.  The
+profile lock is often taken nested, but it is guaranteed to be in a lock
+safe order and not the same lock when done, so it is safe.
+
+A third lock type (aa_lock_task_release) is given to the profile lock
+when it is taken in soft irq context during task release (aa_release).
+This is to avoid a false positive between the task lock and the profile
+lock.  In task context the profile lock wraps the task lock with irqs
+off, but the kernel takes the task lock with irqs enabled.  This won't
+result in a deadlock because for a deadlock to occur the kernel must
+take dead task A's lock (irqs on), the rcu callback hook freeing
+dead task A must be run and AppArmor must be changing the profile on
+dead task A.  The kernel should not be taking a dead task's task_lock
+at the same time the task is being freed by task rcu cleanup other wise
+the task would not be out of its quiescent period.
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -1081,8 +1081,8 @@ void aa_release(struct task_struct *task
 	 * sufficient to prevent the replacement race so we do not lock
 	 * the task.
 	 *
-	 * lock_dep reports a false 'possible irq lock inversion dependency'
-	 * between the profile lock and the task_lock.
+	 * Use lock subtyping to avoid lockdep reporting a false irq
+	 * possible inversion between the task_lock and profile_lock
 	 *
 	 * We also avoid taking the task_lock here because lock_dep
 	 * would report another false {softirq-on-W} potential irq_lock
@@ -1095,7 +1095,7 @@ void aa_release(struct task_struct *task
 repeat:
 	profile = aa_get_profile(task);
 	if (profile) {
-		lock_profile(profile);
+		lock_profile_nested(profile, aa_lock_task_release);
 		cxt = aa_task_context(task);
 		if (unlikely(!cxt || cxt->profile != profile)) {
 			unlock_profile(profile);

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 43/45] Switch to vfs_permission() in do_path_lookup()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (41 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 42/45] AppArmor: add lock subtyping so lockdep does not report false dependencies jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 44/45] Switch to vfs_permission() in sys_fchdir() jjohansen
                   ` (2 subsequent siblings)
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher

[-- Attachment #1: do_path_lookup-nameidata.diff --]
[-- Type: text/plain, Size: 1079 bytes --]

Switch from file_permission() to vfs_permission() in do_path_lookup():
this avoids calling permission() with a NULL nameidata here.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 fs/namei.c |   13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1130,25 +1130,24 @@ static int fastcall do_path_lookup(int d
 		nd->dentry = dget(fs->pwd);
 		read_unlock(&fs->lock);
 	} else {
-		struct dentry *dentry;
-
 		file = fget_light(dfd, &fput_needed);
 		retval = -EBADF;
 		if (!file)
 			goto out_fail;
 
-		dentry = file->f_path.dentry;
+		nd->dentry = file->f_path.dentry;
+		nd->mnt = file->f_path.mnt;
 
 		retval = -ENOTDIR;
-		if (!S_ISDIR(dentry->d_inode->i_mode))
+		if (!S_ISDIR(nd->dentry->d_inode->i_mode))
 			goto fput_fail;
 
-		retval = file_permission(file, MAY_EXEC);
+		retval = vfs_permission(nd, MAY_EXEC);
 		if (retval)
 			goto fput_fail;
 
-		nd->mnt = mntget(file->f_path.mnt);
-		nd->dentry = dget(dentry);
+		mntget(nd->mnt);
+		dget(nd->dentry);
 
 		fput_light(file, fput_needed);
 	}

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 44/45] Switch to vfs_permission() in sys_fchdir()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (42 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 43/45] Switch to vfs_permission() in do_path_lookup() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 11:06 ` [AppArmor 45/45] Fix file_permission() jjohansen
  2007-05-14 13:50 ` [AppArmor 00/45] AppArmor security module overview John Johansen
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher

[-- Attachment #1: sys_fchdir-nameidata.diff --]
[-- Type: text/plain, Size: 1123 bytes --]

Switch from file_permission() to vfs_permission() in sys_fchdir(): this
avoids calling permission() with a NULL nameidata here.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 fs/open.c |   16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

--- a/fs/open.c
+++ b/fs/open.c
@@ -440,10 +440,8 @@ out:
 
 asmlinkage long sys_fchdir(unsigned int fd)
 {
+	struct nameidata nd;
 	struct file *file;
-	struct dentry *dentry;
-	struct inode *inode;
-	struct vfsmount *mnt;
 	int error;
 
 	error = -EBADF;
@@ -451,17 +449,17 @@ asmlinkage long sys_fchdir(unsigned int 
 	if (!file)
 		goto out;
 
-	dentry = file->f_path.dentry;
-	mnt = file->f_path.mnt;
-	inode = dentry->d_inode;
+	nd.dentry = file->f_path.dentry;
+	nd.mnt = file->f_path.mnt;
+	nd.flags = 0;
 
 	error = -ENOTDIR;
-	if (!S_ISDIR(inode->i_mode))
+	if (!S_ISDIR(nd.dentry->d_inode->i_mode))
 		goto out_putf;
 
-	error = file_permission(file, MAY_EXEC);
+	error = vfs_permission(&nd, MAY_EXEC);
 	if (!error)
-		set_fs_pwd(current->fs, mnt, dentry);
+		set_fs_pwd(current->fs, nd.mnt, nd.dentry);
 out_putf:
 	fput(file);
 out:

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 45/45] Fix file_permission()
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (43 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 44/45] Switch to vfs_permission() in sys_fchdir() jjohansen
@ 2007-05-14 11:06 ` jjohansen
  2007-05-14 13:50 ` [AppArmor 00/45] AppArmor security module overview John Johansen
  45 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-05-14 11:06 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-security-module, linux-fsdevel, Andreas Gruenbacher

[-- Attachment #1: file_permission-nameidata.diff --]
[-- Type: text/plain, Size: 695 bytes --]

We cannot easily switch from file_permission() to vfs_permission()
everywhere, so fix file_permission() to not use a NULL nameidata
for the remaining users.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 fs/namei.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -296,7 +296,13 @@ int vfs_permission(struct nameidata *nd,
  */
 int file_permission(struct file *file, int mask)
 {
-	return permission(file->f_path.dentry->d_inode, mask, NULL);
+	struct nameidata nd;
+	
+	nd.dentry = file->f_path.dentry;
+	nd.mnt = file->f_path.mnt;
+	nd.flags = LOOKUP_ACCESS;
+
+	return permission(nd.dentry->d_inode, mask, &nd);
 }
 
 /*

-- 

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 00/45] AppArmor security module overview
  2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
                   ` (44 preceding siblings ...)
  2007-05-14 11:06 ` [AppArmor 45/45] Fix file_permission() jjohansen
@ 2007-05-14 13:50 ` John Johansen
  45 siblings, 0 replies; 240+ messages in thread
From: John Johansen @ 2007-05-14 13:50 UTC (permalink / raw)
  To: jjohansen; +Cc: linux-kernel, linux-security-module, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 4215 bytes --]

and with the actual introductory text this time

This post contains patches to include the AppArmor application security
framework, with request for inclusion.  It contains fixes for almost
all of the feedback received from the previous post.  A second follow
up posting will address passing NULL nameidata.

Changes since previous post:

 - Refactor d_path() patches: Separate changes to d_path(), getcwd(),
   and /proc/mounts from __d_path() cleanups.

 - Switch from file_permission() to vfs_permission() in do_path_lookup()
   and sys_fchdir(): this avoids calling permission() with a NULL nameidata
   there.

 - Fix file_permission() to not use NULL nameidata for its remaining users:
   it makes little sense to replace file_permission() with vfs_permission()
   everywhere.

 - Remove special casing for access to /proc/self/attr/current by adding
   rules to policy user side.

 - Remove redundant fn's in lsm.c by calling cap functions directly from
   the security operations vector.

 - Disallow ptracing process with different namespace.

 - Use beX_to_cpu instead on ntoX in dfa unpack code.

 - Fix potential overflow in unpack bounds checking.

 - Limit profile recursion depth to 1 level.

 - Factor out sysctl pathname code from selinux to add generic
   sysctl_pathname() function in kernel/sysctl.c. Replace special casing of
   sysctl write with finer grained mediation using sysctl_pathname() function
   to provide pathname for sysctl mediation.

 - Escape special characters in pathnames when used in audit messages.

 - Remove use of task->comm from audit messages.  The use of task->comm was
   incorrect and only used as a human readable hint.

 - Some structural cleanups on apparmors audit code paths.

 - Set LOOKUP_CONTINUE flag when checking parent permissions.  This allows
   permission functions to tell between parent and leaf checks. Check for
   (LOOKUP_PARENT | LOOKUP_CONTINUE) in the inode_permission apparmor hook.

 - Drop rejection of CLONE_NEWNS since the kernel already requires
   CAP_SYS_ADMIN.

 - Add a missing dput() in apparmorfs_detry_refcount().

 - remove kernel doc style comment header from comments that are not
   in kernel doc format

 - use lock subtyping to address lockdep reporint  possible irq lock
   inversion


The patch series consists of five areas:

 (1) Pass struct vfsmount through to LSM hooks.

 (2) Fixes and improvements to __d_path():

     (a) make it unambiguous and exclude unreachable paths from
         /proc/mounts,

     (b) make its result consistent in the face of remounts,

     (c) introduce d_namespace_path(), a variant of d_path that goes up
         to the namespace root instead of the chroot.

     (d) the behavior of d_path() and getcwd() remain unchanged, and
     there is no hidding of unreachable paths in /proc/mounts.  The
     patches addressing these have been seperated from the AppArmor
     submission and will be introduced at a later date.
 
     Part (a) has been in the -mm tree for a while; this series includes
     an updated copy of the -mm patch. Parts (b) and (c) shouldn't be too
     controversial.

 (3) Be able to distinguish file descriptor access from access by name
     in LSM hooks.

     Applications expect different behavior from file descriptor
     accesses and accesses by name in some cases. We need to pass this
     information down the LSM hooks to allow AppArmor to tell which is
     which.

 (4) Convert the selinux sysctl pathname computation code into a standalone
     function.

 (5) The AppArmor LSM itself.

     (See below.)

A tarball of the kernel patches, base user-space utilities, example
profiles, and technical documentation (including a walk-through) are
available at:

  http://forgeftp.novell.com//apparmor/LKML_Submission-May_07/

Explaining the AppArmor design in detail would take by far too much
space here, so let me refer you to the technical documentation for that.
Included is a low-level walk-through of the system and basic tools, and
some examples.  The manual pages included in the apparmor-parser package
are worth a read as well.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 35/45] Allow permission functions to tell between parent and leaf checks
  2007-05-14 11:06 ` [AppArmor 35/45] Allow permission functions to tell between parent and leaf checks jjohansen
@ 2007-05-15  9:08   ` Pavel Machek
  0 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-05-15  9:08 UTC (permalink / raw)
  To: jjohansen
  Cc: linux-kernel, linux-security-module, linux-fsdevel, Andreas Gruenbacher

Hi!

> Set the LOOKUP_CONTINUE flag when checking parent permissions. This allows
> permission functions to tell between parent and leaf checks.
> 
> Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

I guess you should sign this off.


> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -1409,6 +1409,10 @@ static int may_delete(struct inode *dir,
>  	BUG_ON(victim->d_parent->d_inode != dir);
>  	audit_inode_child(victim->d_name.name, victim->d_inode, dir);
>  
> +#if 0
> +	if (nd)
> +		nd->flags |= LOOKUP_CONTINUE;
> +#endif

We don't add disabled code to kernel.
							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 37/45] AppArmor: Main Part
  2007-05-14 11:06 ` [AppArmor 37/45] AppArmor: Main Part jjohansen
@ 2007-05-15  9:12   ` Pavel Machek
  0 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-05-15  9:12 UTC (permalink / raw)
  To: jjohansen
  Cc: linux-kernel, linux-security-module, linux-fsdevel, Andreas Gruenbacher

Hi!

> The underlying functions by which the AppArmor LSM hooks are implemented.
> 
> Signed-off-by: John Johansen <jjohansen@suse.de>
> Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

> +#include "inline.h"

Select a better name for include?

> +static inline void aa_permerror2result(int perm_result, struct aa_audit *sa)

Betternameoffunction?

> +/**
> + * mangle -- escape special characters in str
> + * @str: string to escape
> + * @buffer: buffer containing str
> + *
> + * Escape special characters in @str, which is contained in @buffer. @str must
> + * be aligned to the end of the buffer, and the space between @buffer and @str
> + * may be used for escaping.
> + *
> + * Returns @str if no escaping was necessary, a pointer to the beginning of the
> + * escaped string, or NULL if there was not enough space in @buffer.  When
> + * called with a NULL buffer, the return value tells whether any escaping is
> + * necessary.
> + */
> +static const char *mangle(const char *str, char *buffer)
> +{
> +	static const char c_escape[] = {
> +		['\a'] = 'a',	['\b'] = 'b',
> +		['\f'] = 'f',	['\n'] = 'n',
> +		['\r'] = 'r',	['\t'] = 't',
> +		['\v'] = 'v',
> +		[' '] = ' ',	['\\'] = '\\',
> +	};
> +	const char *s;
> +	char *t, c;
> +
> +#define mangle_escape(c)						\
> +	unlikely((unsigned char)(c) < ARRAY_SIZE(c_escape) &&		\
> +		 c_escape[(unsigned char)c])
> +
> +	for (s = (char *)str; (c = *s) != '\0'; s++)
> +		if (mangle_escape(c))
> +			goto escape;
> +	return str;
> +
> +escape:
> +	if (!buffer)
> +		return NULL;
> +	for (s = str, t = buffer; (c = *s) != '\0'; s++) {
> +		if (mangle_escape(c)) {
> +			if (t == s)
> +				return NULL;
> +			*t++ = '\\';
> +			*t++ = c_escape[(unsigned char)c];
> +		} else
> +			*t++ = c;
> +	}
> +	*t++ = '\0';
> +
> +#undef mangle_escape
> +
> +	return buffer;
> +}

I do not think we want this in kernel.

							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-05-14 11:06 ` [AppArmor 38/45] AppArmor: Module and LSM hooks jjohansen
@ 2007-05-15  9:14   ` Pavel Machek
  2007-05-23 16:16     ` Andreas Gruenbacher
  0 siblings, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-05-15  9:14 UTC (permalink / raw)
  To: jjohansen
  Cc: linux-kernel, linux-security-module, linux-fsdevel, Andreas Gruenbacher


> Module parameters, LSM hooks, initialization and teardown.
> 
> Signed-off-by: John Johansen <jjohansen@suse.de>
> Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

> +/* Maximum pathname length before accesses will start getting rejected */
> +unsigned int apparmor_path_max = 2 * PATH_MAX;
> +module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
> +MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");

WTF? Why is this configurable?
							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-05-14 11:06 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching jjohansen
@ 2007-05-15  9:20   ` Pavel Machek
  2007-06-04 21:03     ` Andreas Gruenbacher
  0 siblings, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-05-15  9:20 UTC (permalink / raw)
  To: jjohansen
  Cc: linux-kernel, linux-security-module, linux-fsdevel, Andreas Gruenbacher

Hi!

> Pathname matching, transition table loading, profile loading and
> manipulation.

So we get small interpretter of state machines, and reason we need is
is 'apparmor is misdesigned and works with paths when it should have
worked with handles'.

If you solve the 'new file problem', aa becomes subset of selinux..
And I'm pretty sure patch will be nicer than this.

							Pavel

> +int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
> +{
> +	int hsize, i;
> +	int error = -ENOMEM;
> +
> +	/* get dfa table set header */
> +	if (size < sizeof(struct table_set_header))
> +		goto fail;
> +
> +	if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
> +		goto fail;
> +
> +	hsize = ntohl(*(u32 *)(blob + 4));
> +	if (size < hsize)
> +		goto fail;
> +
> +	blob += hsize;
> +	size -= hsize;
> +
> +	error = -EPROTO;
> +	while (size > 0) {
> +		struct table_header *table;
> +		table = unpack_table(blob, size);
> +		if (!table)
> +			goto fail;
> +
> +		switch(table->td_id) {
> +		case YYTD_ID_ACCEPT:
> +		case YYTD_ID_BASE:
> +			dfa->tables[table->td_id - 1] = table;
> +			if (table->td_flags != YYTD_DATA32)
> +				goto fail;
> +			break;
> +		case YYTD_ID_DEF:
> +		case YYTD_ID_NXT:
> +		case YYTD_ID_CHK:
> +			dfa->tables[table->td_id - 1] = table;
> +			if (table->td_flags != YYTD_DATA16)
> +				goto fail;
> +			break;
> +		case YYTD_ID_EC:
> +			dfa->tables[table->td_id - 1] = table;
> +			if (table->td_flags != YYTD_DATA8)
> +				goto fail;
> +			break;
> +		default:
> +			kfree(table);
> +			goto fail;
> +		}
> +
> +		blob += table_size(table->td_lolen, table->td_flags);
> +		size -= table_size(table->td_lolen, table->td_flags);
> +	}
> +
> +	return 0;
> +
> +fail:
> +	for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
> +		if (dfa->tables[i]) {
> +			kfree(dfa->tables[i]);
> +			dfa->tables[i] = NULL;
> +		}
> +	}
> +	return error;
> +}
> +
> +/**
> + * verify_dfa - verify that all the transitions and states in the dfa tables
> + *              are in bounds.
> + * @dfa: dfa to test
> + *
> + * assumes dfa has gone through the verification done by unpacking
> + */
> +int verify_dfa(struct aa_dfa *dfa)
> +{
> +	size_t i, state_count, trans_count;
> +	int error = -EPROTO;
> +
> +	/* check that required tables exist */
> +	if (!(dfa->tables[YYTD_ID_ACCEPT -1 ] &&
> +	      dfa->tables[YYTD_ID_DEF - 1] &&
> +	      dfa->tables[YYTD_ID_BASE - 1] &&
> +	      dfa->tables[YYTD_ID_NXT - 1] &&
> +	      dfa->tables[YYTD_ID_CHK - 1]))
> +		goto out;
> +
> +	/* accept.size == default.size == base.size */
> +	state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
> +	if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
> +	      state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen))
> +		goto out;
> +
> +	/* next.size == chk.size */
> +	trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
> +	if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
> +		goto out;
> +
> +	/* if equivalence classes then its table size must be 256 */
> +	if (dfa->tables[YYTD_ID_EC - 1] &&
> +	    dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
> +		goto out;
> +
> +	for (i = 0; i < state_count; i++) {
> +		if (DEFAULT_TABLE(dfa)[i] >= state_count)
> +			goto out;
> +		if (BASE_TABLE(dfa)[i] >= trans_count + 256)
> +			goto out;
> +	}
> +
> +	for (i = 0; i < trans_count ; i++) {
> +		if (NEXT_TABLE(dfa)[i] >= state_count)
> +			goto out;
> +		if (CHECK_TABLE(dfa)[i] >= state_count)
> +			goto out;
> +	}
> +
> +	error = 0;
> +out:
> +	return error;
> +}
> +
> +struct aa_dfa *aa_match_alloc(void)
> +{
> +	return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
> +}
> +
> +void aa_match_free(struct aa_dfa *dfa)
> +{
> +	if (dfa) {
> +		int i;
> +
> +		for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
> +			kfree(dfa->tables[i]);
> +	}
> +	kfree(dfa);
> +}
> +
> +/**
> + * aa_dfa_match - match @path against @dfa starting in @state
> + * @dfa: the dfa to match @path against
> + * @state: the state to start matching in
> + * @path: the path to match against the dfa
> + *
> + * aa_dfa_match will match the full path length and return the state it
> + * finished matching in. The final state is used to look up the accepting
> + * label.
> + */
> +unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str)
> +{
> +	u16 *def = DEFAULT_TABLE(dfa);
> +	u32 *base = BASE_TABLE(dfa);
> +	u16 *next = NEXT_TABLE(dfa);
> +	u16 *check = CHECK_TABLE(dfa);
> +	unsigned int state = 1, pos;
> +
> +	/* current state is <state>, matching character *str */
> +	if (dfa->tables[YYTD_ID_EC - 1]) {
> +		u8 *equiv = EQUIV_TABLE(dfa);
> +		while (*str) {
> +			pos = base[state] + equiv[(u8)*str++];
> +			if (check[pos] == state)
> +				state = next[pos];
> +			else
> +				state = def[state];
> +		}
> +	} else {
> +		while (*str) {
> +			pos = base[state] + (u8)*str++;
> +			if (check[pos] == state)
> +				state = next[pos];
> +			else
> +				state = def[state];
> +		}
> +	}
> +	return ACCEPT_TABLE(dfa)[state];
> +}

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-05-15  9:14   ` Pavel Machek
@ 2007-05-23 16:16     ` Andreas Gruenbacher
  2007-06-04 10:55       ` Pavel Machek
  0 siblings, 1 reply; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-05-23 16:16 UTC (permalink / raw)
  To: Pavel Machek
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Tuesday 15 May 2007 11:14, Pavel Machek wrote:
> Why is this configurable? 

The maximum length of a pathname is an arbitrary limit: we don't want to 
allocate arbitrary amounts of of kernel memory for pathnames so we introduce 
this limit and set it to a reasonable value. In the unlikely case that 
someone uses insanely long pathnames, this limit can be increased.

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-05-23 16:16     ` Andreas Gruenbacher
@ 2007-06-04 10:55       ` Pavel Machek
  2007-06-04 11:25         ` Andreas Gruenbacher
  0 siblings, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-06-04 10:55 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Wed 2007-05-23 18:16:45, Andreas Gruenbacher wrote:
> On Tuesday 15 May 2007 11:14, Pavel Machek wrote:
> > Why is this configurable? 
> 
> The maximum length of a pathname is an arbitrary limit: we don't want to 
> allocate arbitrary amounts of of kernel memory for pathnames so we introduce 
> this limit and set it to a reasonable value. In the unlikely case that 
> someone uses insanely long pathnames, this limit can be increased.

vfs does not have configurable pathname limit, and I do not see what
is so special about AA to require this kind of uglyness.

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-04 10:55       ` Pavel Machek
@ 2007-06-04 11:25         ` Andreas Gruenbacher
  2007-06-04 11:35           ` Pavel Machek
  0 siblings, 1 reply; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-04 11:25 UTC (permalink / raw)
  To: Pavel Machek
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Monday 04 June 2007 12:55, Pavel Machek wrote:
> On Wed 2007-05-23 18:16:45, Andreas Gruenbacher wrote:
> > On Tuesday 15 May 2007 11:14, Pavel Machek wrote:
> > > Why is this configurable?
> >
> > The maximum length of a pathname is an arbitrary limit: we don't want to
> > allocate arbitrary amounts of of kernel memory for pathnames so we
> > introduce this limit and set it to a reasonable value. In the unlikely
> > case that someone uses insanely long pathnames, this limit can be
> > increased.
>
> vfs does not have configurable pathname limit, and I do not see what
> is so special about AA to require this kind of uglyness.

You very well know that the vfs has a limit of PATH_MAX characters (4096) for 
pathnames. This means that at most that many characters can be passed at 
once. 

I've really got enough of your perpetual unfounded rants.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-04 11:25         ` Andreas Gruenbacher
@ 2007-06-04 11:35           ` Pavel Machek
  2007-06-04 11:42             ` Andreas Gruenbacher
  0 siblings, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-06-04 11:35 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Mon 2007-06-04 13:25:30, Andreas Gruenbacher wrote:
> On Monday 04 June 2007 12:55, Pavel Machek wrote:
> > On Wed 2007-05-23 18:16:45, Andreas Gruenbacher wrote:
> > > On Tuesday 15 May 2007 11:14, Pavel Machek wrote:
> > > > Why is this configurable?
> > >
> > > The maximum length of a pathname is an arbitrary limit: we don't want to
> > > allocate arbitrary amounts of of kernel memory for pathnames so we
> > > introduce this limit and set it to a reasonable value. In the unlikely
> > > case that someone uses insanely long pathnames, this limit can be
> > > increased.
> >
> > vfs does not have configurable pathname limit, and I do not see what
> > is so special about AA to require this kind of uglyness.
> 
> You very well know that the vfs has a limit of PATH_MAX characters (4096) for 
> pathnames. This means that at most that many characters can be passed at 
> once. 

Sorry then. Why not reuse the PATH_MAX when it exists already?
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-04 11:35           ` Pavel Machek
@ 2007-06-04 11:42             ` Andreas Gruenbacher
  2007-06-04 13:12               ` Pavel Machek
  0 siblings, 1 reply; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-04 11:42 UTC (permalink / raw)
  To: Pavel Machek
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Monday 04 June 2007 13:35, Pavel Machek wrote:
> On Mon 2007-06-04 13:25:30, Andreas Gruenbacher wrote:
> > On Monday 04 June 2007 12:55, Pavel Machek wrote:
> > > On Wed 2007-05-23 18:16:45, Andreas Gruenbacher wrote:
> > > > On Tuesday 15 May 2007 11:14, Pavel Machek wrote:
> > > > > Why is this configurable?
> > > >
> > > > The maximum length of a pathname is an arbitrary limit: we don't want
> > > > to allocate arbitrary amounts of of kernel memory for pathnames so we
> > > > introduce this limit and set it to a reasonable value. In the
> > > > unlikely case that someone uses insanely long pathnames, this limit
> > > > can be increased.
> > >
> > > vfs does not have configurable pathname limit, and I do not see what
> > > is so special about AA to require this kind of uglyness.
> >
> > You very well know that the vfs has a limit of PATH_MAX characters (4096)
> > for pathnames. This means that at most that many characters can be passed
> > at once.

What users can do is something like this:

  chdir("some/long/path");
  chdir("some/even/longer/path");
  ...

and the total length of the path can then exceed PATH_MAX characters. We can 
only accept pathnames up to some upper limit, and we need to somehow define 
what that limit is supposed to be. We could use PATH_MAX or some other 
arbitrary number. In most situations PATH_MAX will be fine, but that's not 
always guaranteed to be the case. So what's wrong about making this 
configurable for special situations that we might run into? Module parameters 
are *really* dead cheap.

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-04 11:42             ` Andreas Gruenbacher
@ 2007-06-04 13:12               ` Pavel Machek
  2007-06-04 14:30                 ` Andreas Gruenbacher
  0 siblings, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-06-04 13:12 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

Hi!

> > > You very well know that the vfs has a limit of PATH_MAX characters (4096)
> > > for pathnames. This means that at most that many characters can be passed
> > > at once.
> 
> What users can do is something like this:
> 
>   chdir("some/long/path");
>   chdir("some/even/longer/path");
>   ...
> 
> and the total length of the path can then exceed PATH_MAX characters. We can 
> only accept pathnames up to some upper limit, and we need to somehow define 
> what that limit is supposed to be. We could use PATH_MAX or some other 
> arbitrary number. In most situations PATH_MAX will be fine, but that's not 
> always guaranteed to be the case. So what's wrong about making this 
> configurable for special situations that we might run into? Module parameters 
> are *really* dead cheap.

Parameters are cheap, but this one is ugly.

How will kernel work with very long paths? I'd suspect some problems,
if path is 1MB long and I attempt to print it in /proc
somewhere. Perhaps vfs should be modified not to allow such crazy
paths? But placing limit in aa is ugly.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-04 13:12               ` Pavel Machek
@ 2007-06-04 14:30                 ` Andreas Gruenbacher
  2007-06-06 13:09                   ` Stephen Smalley
  2007-06-09 12:58                   ` Pavel Machek
  0 siblings, 2 replies; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-04 14:30 UTC (permalink / raw)
  To: Pavel Machek
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Monday 04 June 2007 15:12, Pavel Machek wrote:
> How will kernel work with very long paths? I'd suspect some problems,
> if path is 1MB long and I attempt to print it in /proc
> somewhere.

Pathnames are only used for informational purposes in the kernel, except in 
AppArmor of course. /proc only uses pathnames in a few places, 
but /proc/mounts will silently fail and produce garbage entries. That's not 
ideal of course; we should fix that somehow.

Note that this has nothing to do with the AppArmor discussion ...

> Perhaps vfs should be modified not to allow such crazy paths? But placing
> limit in aa is ugly. 

Dream on. Redefining fundamental vfs semantics is not an option; we should 
rather make sure that we fail gracefully. Considering the alternatives, I 
still prefer the configurable limit. That's way more useful than allowing a 
process to DOS the kernel with AppArmor.

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-05-15  9:20   ` Pavel Machek
@ 2007-06-04 21:03     ` Andreas Gruenbacher
  2007-06-06 13:26       ` Stephen Smalley
  0 siblings, 1 reply; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-04 21:03 UTC (permalink / raw)
  To: Pavel Machek
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Tuesday 15 May 2007 11:20, Pavel Machek wrote:
> Hi!
> 
> > Pathname matching, transition table loading, profile loading and
> > manipulation.
> 
> So we get small interpretter of state machines, and reason we need is
> is 'apparmor is misdesigned and works with paths when it should have
> worked with handles'.

I assume you mean labels instead of handles.

AppArmor's design is around paths not labels, and independent of whether or 
not you like AppArmor, this design leads to a useful security model distinct 
from the SELinux security model (which is useful in its own ways). The 
differences between those models cannot be argued away, neither is a subset 
of the other, and neither is a misdesign. I would be thankful if you could 
stop spreading this lie.

> If you solve the 'new file problem', aa becomes subset of selinux.
> And I'm pretty sure patch will be nicer than this. 

You are quite mistaken. SELinux turns pathnames into labels when it initially 
labels all files (when a policy is rolled out), whereas AppArmor computes 
the "label" of each file when a file is opened. The two models start to 
diverge as soon as files are renamed: in SELinux, labels stick with the 
files. In AppArmor, "labels" stick with the names.

So what you advocate for is a hybrid between the SELinux and the AppArmor 
model, not a superset.

It could be that the SELinux folks will solve the issues they are having with 
new files using something better than restorecond in the future, perhaps even 
an in-kernel mechanism (although I somewhat doubt it). But then again, their 
basic model makes sense even without any live file relabeling, and so that's 
probably not very high up on the priority list.

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-04 14:30                 ` Andreas Gruenbacher
@ 2007-06-06 13:09                   ` Stephen Smalley
  2007-06-10 23:10                     ` Andreas Gruenbacher
  2007-06-09 12:58                   ` Pavel Machek
  1 sibling, 1 reply; 240+ messages in thread
From: Stephen Smalley @ 2007-06-06 13:09 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Mon, 2007-06-04 at 16:30 +0200, Andreas Gruenbacher wrote:
> On Monday 04 June 2007 15:12, Pavel Machek wrote:
> > How will kernel work with very long paths? I'd suspect some problems,
> > if path is 1MB long and I attempt to print it in /proc
> > somewhere.
> 
> Pathnames are only used for informational purposes in the kernel, except in 
> AppArmor of course.

I don't mean this as a flame, but isn't the above statement the very
crux of this discussion?  Why should AppArmor be different from the rest
of the kernel in its usage of pathnames (basis for decisions vs.
informational reporting to userspace)?  And if it is ok for AppArmor to
generate and use pathnames as its basis of decisions on each open, then
is it also ok for audit, inotify, and others to use them in the same
manner?  If the audit developers or inotify developers had come with
patches that used d_path or equivalent in the same manner as AppArmor,
don't you think they would have gotten the same resistance?  And if you
are truly trying to create a mechanism (in AppArmor) that you can
ultimately apply widely to the system (going beyond AppArmor's original
limited focus on a small set of network-facing daemons), aren't you
concerned about the implications of having to generate a pathname on
each open just to decide what to do?  Is this really the "path" you want
to take ;)?

Another question:  it seems like the read-only bind mount folks gave up
on propagating the vfsmounts down and switched to a rather different
approach (checking near the entry points, using mount writer counters).
So similarly, what makes AppArmor fundamentally different that it
wouldn't take a similar approach to what they are doing vs. propagating
the vfsmounts down?  Or do you think they made the wrong choice?  If so,
why?

Just trying to understand your position better...

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-04 21:03     ` Andreas Gruenbacher
@ 2007-06-06 13:26       ` Stephen Smalley
  2007-06-06 17:32         ` Greg KH
  2007-06-08 22:03         ` Andreas Gruenbacher
  0 siblings, 2 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-06 13:26 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Mon, 2007-06-04 at 23:03 +0200, Andreas Gruenbacher wrote:
> On Tuesday 15 May 2007 11:20, Pavel Machek wrote:
> > Hi!
> > 
> > > Pathname matching, transition table loading, profile loading and
> > > manipulation.
> > 
> > So we get small interpretter of state machines, and reason we need is
> > is 'apparmor is misdesigned and works with paths when it should have
> > worked with handles'.
> 
> I assume you mean labels instead of handles.
> 
> AppArmor's design is around paths not labels, and independent of whether or 
> not you like AppArmor, this design leads to a useful security model distinct 
> from the SELinux security model (which is useful in its own ways). The 
> differences between those models cannot be argued away, neither is a subset 
> of the other, and neither is a misdesign. I would be thankful if you could 
> stop spreading this lie.

I have a hard time distinguishing AppArmor's "model" from its
implementation; every time we suggest that one might emulate much of
AppArmor's functionality on SELinux (as in SEEdit), someone points to a
specific characteristic of the AppArmor implementation that cannot be
emulated in this manner.  But is that implementation characteristic an
actual requirement or just how it happens to have been done to date in
AA?  And I get the impression that even if we extended SELinux in
certain ways to ease such emulation, the AA folks would never be
satisfied because the implementation would still differ.  Can we
separate the desired functionality and actual requirements from the
implementation specifics?

> > If you solve the 'new file problem', aa becomes subset of selinux.
> > And I'm pretty sure patch will be nicer than this. 
> 
> You are quite mistaken. SELinux turns pathnames into labels when it initially 
> labels all files (when a policy is rolled out), whereas AppArmor computes 
> the "label" of each file when a file is opened. The two models start to 
> diverge as soon as files are renamed: in SELinux, labels stick with the 
> files. In AppArmor, "labels" stick with the names.

I'd argue a bit with that characterization, given that:
- in the case of SELinux, the pathname is never used as a basis for
decisions by the kernel,
- under AA, each file may have an arbitrary set of "labels" or
"policies" applied to it depending on what programs are accessing it and
what names are being used to reference it - there is no system view of
the subjects and objects and thus no way to identify the overall system
policy for a given file.
- names are far less tranquil than labels.
 
> So what you advocate for is a hybrid between the SELinux and the AppArmor 
> model, not a superset.
> 
> It could be that the SELinux folks will solve the issues they are having with 
> new files using something better than restorecond in the future, perhaps even 
> an in-kernel mechanism (although I somewhat doubt it). But then again, their 
> basic model makes sense even without any live file relabeling, and so that's 
> probably not very high up on the priority list.

Live file relabeling (non-tranquility) tends to break one's ability to
show anything about preservation of confidentiality or integrity
(particularly in the absence of complete revocation support).

On the new files issue, it wouldn't be difficult or even a real
divergence from our existing model to introduce the component name (not
a "full" pathname, but the last component) as an additional input to the
decision for labeling new files (along with the existing use of the
creating process' label, the parent directory label, and the kind of new
file) at creation time, and that would reduce the need somewhat to
modify some applications that create files of multiple security contexts
in the same directory.  That would further help the SEEdit folks in
emulating AA on top of SELinux, but as before, I don't get the
impression that the AA folks will ever be satisfied with such an
emulation, not because of any real requirement but merely because they
are tied to their implementation specifics.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-06 13:26       ` Stephen Smalley
@ 2007-06-06 17:32         ` Greg KH
  2007-06-09 23:47           ` Pavel Machek
  2007-06-08 22:03         ` Andreas Gruenbacher
  1 sibling, 1 reply; 240+ messages in thread
From: Greg KH @ 2007-06-06 17:32 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Andreas Gruenbacher, Pavel Machek, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Wed, Jun 06, 2007 at 09:26:26AM -0400, Stephen Smalley wrote:
> On Mon, 2007-06-04 at 23:03 +0200, Andreas Gruenbacher wrote:
> > On Tuesday 15 May 2007 11:20, Pavel Machek wrote:
> > > Hi!
> > > 
> > > > Pathname matching, transition table loading, profile loading and
> > > > manipulation.
> > > 
> > > So we get small interpretter of state machines, and reason we need is
> > > is 'apparmor is misdesigned and works with paths when it should have
> > > worked with handles'.
> > 
> > I assume you mean labels instead of handles.
> > 
> > AppArmor's design is around paths not labels, and independent of whether or 
> > not you like AppArmor, this design leads to a useful security model distinct 
> > from the SELinux security model (which is useful in its own ways). The 
> > differences between those models cannot be argued away, neither is a subset 
> > of the other, and neither is a misdesign. I would be thankful if you could 
> > stop spreading this lie.
> 
> I have a hard time distinguishing AppArmor's "model" from its
> implementation; every time we suggest that one might emulate much of
> AppArmor's functionality on SELinux (as in SEEdit), someone points to a
> specific characteristic of the AppArmor implementation that cannot be
> emulated in this manner.  But is that implementation characteristic an
> actual requirement or just how it happens to have been done to date in
> AA?  And I get the impression that even if we extended SELinux in
> certain ways to ease such emulation, the AA folks would never be
> satisfied because the implementation would still differ.  Can we
> separate the desired functionality and actual requirements from the
> implementation specifics?

That's a really good point, is there a description of the AA "model"
anywhere that we could see to determine if there really is a way to
possibly use the current SELinux internals to show this model to the
user?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-06 13:26       ` Stephen Smalley
  2007-06-06 17:32         ` Greg KH
@ 2007-06-08 22:03         ` Andreas Gruenbacher
  2007-06-09  0:17           ` Greg KH
  2007-06-11 15:16           ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Stephen Smalley
  1 sibling, 2 replies; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-08 22:03 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Wednesday 06 June 2007 15:26, Stephen Smalley wrote:
> On Mon, 2007-06-04 at 23:03 +0200, Andreas Gruenbacher wrote:
> > [...] SELinux turns pathnames into labels when it
> > initially labels all files (when a policy is rolled out), whereas
> > AppArmor computes the "label" of each file when a file is opened. The two
> > models start to diverge as soon as files are renamed: in SELinux, labels
> > stick with the files. In AppArmor, "labels" stick with the names.
>
> I'd argue a bit with that characterization, given that:
> - in the case of SELinux, the pathname is never used as a basis for
> decisions by the kernel,

Indeed, the kernel component of SELinux only uses file labels for making file 
access decisions and not pathnames. But those labels were initially created  
by a trusted process (e.g. restorecon) based on pathnames, and this initial 
labeling is an essential part of the SELinux model. So in a sense, 
disregarding creation and relabeling of files, one could argue that SELinux 
makes decisions based on the pathnames that files had when they were labeled.

In SELinux, labels are the only thing that distinguishes between files. So if 
at one point you find that you need to distinguish between files that share a 
label, you have to split the label and reclassify the files in addition to 
adjusting the policy. Again, the usual approach for reclassifying files will 
probably be pathname based.

In contrast, AppArmor does not use labels, and the pathnames at the time of 
access distinguish between files. Since files do not have labels, no 
relabeling is necessary in order to change policy.

> - under AA, each file may have an arbitrary set of "labels" or
> "policies" applied to it depending on what programs are accessing it and
> what names are being used to reference it - there is no system view of
> the subjects and objects and thus no way to identify the overall system
> policy for a given file.

Look at it this way: under SELinux, the set of files that share a label forms 
an equivalence class -- they are all treated identically by the system's 
security policy. The rules in AppArmor profiles also define equivalence 
classes in the sense that they partition the filesystem namespace into sets 
of files that are treated identically, but this classification is not 
explicit -- the entire rule base contributes to the classification. This 
doesn't mean that there is not a global policy, just that the policy is 
modeled differently. The equivalence classes are not directly obvious from 
the AA profiles.

Contrast this with SEEdit, which compiles AA-style rules into labels (and thus 
equivalence classes). The resulting SELinux policy is a static snapshot that 
cannot easily accommodate rule base changes, is more limited with respect to 
new files (which would likely be fixable), and behaves differently in complex 
ways with file renames. What's more, most likely the compiled policy will be 
anywhere from very hard to impossible to analyze, so you pretty much lose on 
all ends.

I'm not saying that labels are crap and that SELinux is wrong. In fact, labels 
are useful for some things like model verification and information flow 
analysis. What I'm saying is that AppArmor and SELinux implement different 
models, and those models cannot be modeled in terms of each other.

Note that I'm not embarking on implementation aspects here at all, only on the 
fundamental model differences.

> - names are far less tranquil than labels.

If I'm getting things right, a tranquil system with respect to labels would be 
one that does not permit re-labeling, while a tranquil system with respect to 
path names would be one that does not permit renaming. Both approaches would 
buy greater analyzability with reduced usability, and both seem unrealistic 
to me. SELinux and AppArmor evidently have different goals, and tranquility 
is more important to SELinux.

AppArmor is meant to be relatively easy to understand, manage, and customize, 
and introducing a labels layer wouldn't help these goals. SELinux is 
applicable in areas where AppArmor is not (e.g., MLS), but this comes at a 
cost. For me the question is not SELinux or AppArmor, but if AppArmor's 
security model is a good solution in common scenarios. In my opinion, 
AppArmor is a better answer than SELinux in a number of scenarios. This gives 
it value, nonwithstanding the fact that SELinux can be taken further.

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-08 22:03         ` Andreas Gruenbacher
@ 2007-06-09  0:17           ` Greg KH
  2007-06-09  1:06             ` david
                               ` (3 more replies)
  2007-06-11 15:16           ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Stephen Smalley
  1 sibling, 4 replies; 240+ messages in thread
From: Greg KH @ 2007-06-09  0:17 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Stephen Smalley, Pavel Machek, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Sat, Jun 09, 2007 at 12:03:57AM +0200, Andreas Gruenbacher wrote:
> AppArmor is meant to be relatively easy to understand, manage, and customize, 
> and introducing a labels layer wouldn't help these goals.

Woah, that describes the userspace side of AA just fine, it means
nothing when it comes to the in-kernel implementation.  There is no
reason that you can't implement the same functionality using some
totally different in-kernel solution if possible.

> SELinux is applicable in areas where AppArmor is not (e.g., MLS), but
> this comes at a cost. For me the question is not SELinux or AppArmor,
> but if AppArmor's security model is a good solution in common
> scenarios. In my opinion, AppArmor is a better answer than SELinux in
> a number of scenarios. This gives it value, nonwithstanding the fact
> that SELinux can be taken further.

I am still not completely certian that we can not properly implement AA
functionality using a SELinux backend solution.  Yes, the current tools
that try to implement this are still lacking, and maybe the kernel needs
to change, but that is possible.

I still want to see a definition of the AA "model" that we can then use
to try to implement using whatever solution works best.  As that seems
to be missing the current argument of if AA can or can not be
implemented using SELinux or something totally different should be
stopped.

So, AA developers, do you have such a document anywhere?  I know there
are some old research papers, do they properly describe the current
model you are trying to implement here?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  0:17           ` Greg KH
@ 2007-06-09  1:06             ` david
  2007-06-09  2:01               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
  2007-06-10  8:34               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Pavel Machek
  2007-06-09  5:18             ` david
                               ` (2 subsequent siblings)
  3 siblings, 2 replies; 240+ messages in thread
From: david @ 2007-06-09  1:06 UTC (permalink / raw)
  To: Greg KH
  Cc: Andreas Gruenbacher, Stephen Smalley, Pavel Machek, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Fri, 8 Jun 2007, Greg KH wrote:

> On Sat, Jun 09, 2007 at 12:03:57AM +0200, Andreas Gruenbacher wrote:
>> AppArmor is meant to be relatively easy to understand, manage, and customize,
>> and introducing a labels layer wouldn't help these goals.
>
> Woah, that describes the userspace side of AA just fine, it means
> nothing when it comes to the in-kernel implementation.  There is no
> reason that you can't implement the same functionality using some
> totally different in-kernel solution if possible.
>
>> SELinux is applicable in areas where AppArmor is not (e.g., MLS), but
>> this comes at a cost. For me the question is not SELinux or AppArmor,
>> but if AppArmor's security model is a good solution in common
>> scenarios. In my opinion, AppArmor is a better answer than SELinux in
>> a number of scenarios. This gives it value, nonwithstanding the fact
>> that SELinux can be taken further.
>
> I am still not completely certian that we can not properly implement AA
> functionality using a SELinux backend solution.  Yes, the current tools
> that try to implement this are still lacking, and maybe the kernel needs
> to change, but that is possible.
>
> I still want to see a definition of the AA "model" that we can then use
> to try to implement using whatever solution works best.  As that seems
> to be missing the current argument of if AA can or can not be
> implemented using SELinux or something totally different should be
> stopped.
>
> So, AA developers, do you have such a document anywhere?  I know there
> are some old research papers, do they properly describe the current
> model you are trying to implement here?

Greg,
   to implement the AA approach useing SELinux you need to have a way that 
files that are renamed or created get tagged with the right label 
automaticaly with no possible race condition.

If this can be done then it _may_ be possible to do the job that AA is 
aimed at with SELinux, but the work nessasary to figure out what lables 
are needed on what file would still make it a non-trivial task.

as I understand it SELinux puts one label on each file, so if you have 
three files accessed by two programs such that
program A accesses files X Y
program B accesses files Y Z

then files X Y and Z all need seperate labels with the policy stateing 
that program A need to access labels X, Y and program B needs to access 
files Y Z

extended out this can come close to giving each file it's own label. AA 
essentially does this and calls the label the path and computes it at 
runtime instead of storing it somewhere.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  1:06             ` david
@ 2007-06-09  2:01               ` Tetsuo Handa
  2007-06-09  3:25                 ` Sean
  2007-06-10  8:34               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Pavel Machek
  1 sibling, 1 reply; 240+ messages in thread
From: Tetsuo Handa @ 2007-06-09  2:01 UTC (permalink / raw)
  To: david; +Cc: linux-kernel, linux-security-module

Hello.

David Lang wrote:
> as I understand it SELinux puts one label on each file, so if you have 
> three files accessed by two programs such that
> program A accesses files X Y
> program B accesses files Y Z
> 
> then files X Y and Z all need separate labels with the policy stateing 
> that program A need to access labels X, Y and program B needs to access 
> files Y Z
> 
> extended out this can come close to giving each file it's own label. AA 
> essentially does this and calls the label the path and computes it at 
> runtime instead of storing it somewhere.

I tried to give each file it's own label, but I couldn't do it.
http://sourceforge.jp/projects/tomoyo/document/nsf2003-en.pdf
There are many elements that forms too strong barrier between pathname and labels,
such as bind-mounts, hard links, newly created files, renamed files, temporary files and so on.
So I gave up giving each file a label that can be used as an identifier,
and took an approach to forbid unneeded mount operations, unneeded link operations,
unneeded renaming operations to keep the pathname represent it's own identifier as much as possible.

Thanks.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  2:01               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
@ 2007-06-09  3:25                 ` Sean
  2007-06-09  4:56                   ` david
  0 siblings, 1 reply; 240+ messages in thread
From: Sean @ 2007-06-09  3:25 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: david, linux-kernel, linux-security-module

On Sat, 9 Jun 2007 11:01:41 +0900
Tetsuo Handa <from-lsm@I-love.SAKURA.ne.jp> wrote:


>From the discussion so far, it seems that the different "model" that AA
is trying to implement, is to do in one step what SELinux does in two
steps; that is trying to combine labelling and enforcement into a
single step.  If this is so, then why can't it just feed its automatic
labelling into SELinux enforcement code?

> I tried to give each file it's own label, but I couldn't do it.
> http://sourceforge.jp/projects/tomoyo/document/nsf2003-en.pdf

That paper seems entirely focused on the automatic generation of policy,
and doesn't seem to help the discussion along.   For instance, there may
be a way to implement AA on top of SELinux _without_ giving each and
every file its own label.

> There are many elements that forms too strong barrier between pathname and labels,
> such as bind-mounts, hard links, newly created files, renamed files, temporary files and so on.
> So I gave up giving each file a label that can be used as an identifier,
> and took an approach to forbid unneeded mount operations, unneeded link operations,
> unneeded renaming operations to keep the pathname represent it's own identifier as much as possible.

AA must have a function that decides the security rights for any given
path in order to make its enforcement decisions.  It must surely be able
to deal with all those things you listed above (bind-mounts,hard links etc).
So why can't those decisions be turned into labels that are fed into SELinux
enforcement code?

Sean.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  3:25                 ` Sean
@ 2007-06-09  4:56                   ` david
  2007-06-09  5:10                     ` Sean
  0 siblings, 1 reply; 240+ messages in thread
From: david @ 2007-06-09  4:56 UTC (permalink / raw)
  To: Sean; +Cc: Tetsuo Handa, linux-kernel, linux-security-module

On Fri, 8 Jun 2007, Sean wrote:

> 
> On Sat, 9 Jun 2007 11:01:41 +0900
> Tetsuo Handa <from-lsm@I-love.SAKURA.ne.jp> wrote:
>
>
> From the discussion so far, it seems that the different "model" that AA
> is trying to implement, is to do in one step what SELinux does in two
> steps; that is trying to combine labelling and enforcement into a
> single step.  If this is so, then why can't it just feed its automatic
> labelling into SELinux enforcement code?
>
>> I tried to give each file it's own label, but I couldn't do it.
>> http://sourceforge.jp/projects/tomoyo/document/nsf2003-en.pdf
>
> That paper seems entirely focused on the automatic generation of policy,
> and doesn't seem to help the discussion along.   For instance, there may
> be a way to implement AA on top of SELinux _without_ giving each and
> every file its own label.
>
>> There are many elements that forms too strong barrier between pathname and labels,
>> such as bind-mounts, hard links, newly created files, renamed files, temporary files and so on.
>> So I gave up giving each file a label that can be used as an identifier,
>> and took an approach to forbid unneeded mount operations, unneeded link operations,
>> unneeded renaming operations to keep the pathname represent it's own identifier as much as possible.
>
> AA must have a function that decides the security rights for any given
> path in order to make its enforcement decisions.  It must surely be able
> to deal with all those things you listed above (bind-mounts,hard links etc).
> So why can't those decisions be turned into labels that are fed into SELinux
> enforcement code?

with AA hardlinks are effectivly different labels on the same file

one of the big problems with SELinux is what label to put on new files 
(including temp files), the AA approach avoids this (frequent) problem 
entirely. In exchange AA picks up the (infrequent) problems of bind-mounts 
and hard-link creation. People have tried to equate these prolems to show 
that AA has just as many problems as SELinux, but you can run systems for 
decades without creating hard-links or bind-mounts

also you seriously misunderstand the AA approach

AA does NOT try to create a security policy for every file on the system.

Instead AA policies are based on specific programs, and each policy states 
what files that program is allowed to access.

if you are useing AA to secure all exposed services on a box you don't 
have to try to write a policy to describe what gcc is allowed to access 
(unless through policy you give one of your exposed services permission to 
run gcc, and even then I'm not sure if gcc would inherit restrictions 
from it's parent or just use it's own)

the resulting policy is much easier to understand (and therefor check) 
becouse it is orders of magnatude smaller then any comprehensive SELinux 
policy.

the AA policy is also much easier to understand becouse you can look at it 
in pieces, understand that piece, and then forget it and move on to the 
next piece.

for example, if you write a policy for apache that limits it's access to 
it's log files, install directories, and document root. then you write a 
policy for your log analysis tool to access it's libraries, report 
directories (under the apache document root) and the apache log files 
(read only), these two policies are independant, you don't have to think 
about one while creating the other (which you would have to do if you had 
to put one label on apache binaries, another on normal web documents, a 
third on the reports, a fourth on the log files, and a fifth on the 
binaries for the log analysis tool. and this is ignoring any overlap in 
libraries!)

AA also lets a sysadmin dip their toe in the water and just write a policy 
for Apache, not for anything else, then write a policy for firefox, then 
write a policy for their mail client, then for bittorrent, etc. there is 
no need or push to try and secure everything all at once, and no need to 
re-label files (and change any policies that used the old labels) when 
you discover a new interaction.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  4:56                   ` david
@ 2007-06-09  5:10                     ` Sean
  2007-06-09  5:38                       ` david
  0 siblings, 1 reply; 240+ messages in thread
From: Sean @ 2007-06-09  5:10 UTC (permalink / raw)
  To: david; +Cc: Tetsuo Handa, linux-kernel, linux-security-module

On Fri, 8 Jun 2007 21:56:06 -0700 (PDT)
david@lang.hm wrote:

> 
> with AA hardlinks are effectivly different labels on the same file

So what?  SELinux can be be altered to accept whatever label you generate.
Pass it whatever label you want.

> one of the big problems with SELinux is what label to put on new files 
> (including temp files), the AA approach avoids this (frequent) problem 
> entirely. In exchange AA picks up the (infrequent) problems of bind-mounts 
> and hard-link creation. People have tried to equate these prolems to show 
> that AA has just as many problems as SELinux, but you can run systems for 
> decades without creating hard-links or bind-mounts

You are thinking about the way SELinux operates today, not how it might
operate to accommodate AA inclusion in the kernel.   Instead of SELinux
always obtaining labels from file attributes, it could ask AA for them
and you could generate them however you like.

> also you seriously misunderstand the AA approach
>
> AA does NOT try to create a security policy for every file on the system.
> 
> Instead AA policies are based on specific programs, and each policy states 
> what files that program is allowed to access.
 
please read a bit more carefully, I was responding to someone else who
made that claim.

> if you are useing AA to secure all exposed services on a box you don't 
> have to try to write a policy to describe what gcc is allowed to access 
> (unless through policy you give one of your exposed services permission to 
> run gcc, and even then I'm not sure if gcc would inherit restrictions 
> from it's parent or just use it's own)
> 
> the resulting policy is much easier to understand (and therefor check) 
> becouse it is orders of magnatude smaller then any comprehensive SELinux 
> policy.

> 
> the AA policy is also much easier to understand becouse you can look at it 
> in pieces, understand that piece, and then forget it and move on to the 
> next piece.

Nobody is asking you to change the AA policy file.  It lives in user space.
But i fail to see the problem in translating it into SELinux terms for
the user transparently.

> for example, if you write a policy for apache that limits it's access to 
> it's log files, install directories, and document root. then you write a 
> policy for your log analysis tool to access it's libraries, report 
> directories (under the apache document root) and the apache log files 
> (read only), these two policies are independant, you don't have to think 
> about one while creating the other (which you would have to do if you had 
> to put one label on apache binaries, another on normal web documents, a 
> third on the reports, a fourth on the log files, and a fifth on the 
> binaries for the log analysis tool. and this is ignoring any overlap in 
> libraries!)

Again, try to think outside the box a bit.  This isn't about using SELinux
as it exists today.  But imagine an SELinux that would ask you to 
supply a security label for each file _instead_ of looking up that label
itself.  Wouldn't that let you implement everything you wanted while still
using much of the SELinux infrastructure that is already in the kernel?

> AA also lets a sysadmin dip their toe in the water and just write a policy 
> for Apache, not for anything else, then write a policy for firefox, then 
> write a policy for their mail client, then for bittorrent, etc. there is 
> no need or push to try and secure everything all at once, and no need to 
> re-label files (and change any policies that used the old labels) when 
> you discover a new interaction.

And so it could remain;  this is about implementation, not model.

Sean

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  0:17           ` Greg KH
  2007-06-09  1:06             ` david
@ 2007-06-09  5:18             ` david
  2007-06-09  5:46               ` Sean
                                 ` (2 more replies)
  2007-06-09 15:05             ` Andreas Gruenbacher
  2007-06-10 17:09             ` Crispin Cowan
  3 siblings, 3 replies; 240+ messages in thread
From: david @ 2007-06-09  5:18 UTC (permalink / raw)
  To: Greg KH
  Cc: Andreas Gruenbacher, Stephen Smalley, Pavel Machek, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Fri, 8 Jun 2007, Greg KH wrote:

> I still want to see a definition of the AA "model" that we can then use
> to try to implement using whatever solution works best.  As that seems
> to be missing the current argument of if AA can or can not be
> implemented using SELinux or something totally different should be
> stopped.

the way I would describe the difference betwen AA and SELinux is:

SELinux is like a default allow IPS system, you have to describe 
EVERYTHING to the system so that it knows what to allow and what to stop.

AA is like a default deny firewall, you describe what you want to happen, 
and it blocks everything else without you even having to realize that it's 
there.

now I know that this isn't a perfect analyogy, that SELinux doesn't allow 
something to happen unless it's been told to let it, but in terms of 
complexity and the amount of work to configure things I think the analogy 
is close.


the fact that the SELinux policy _will_ affect the entire systems means 
one of two things.

1. you have a policy that exactly describes how every part of the system 
operates

or

2. you have a policy that's exessivly permissive in some parts of the 
system becouse 'that works' and you either don't understand that part of 
the system well enough, or don't have time to write a more complete 
policy.

I would argue that with the number of files on a system nowdays (483,000 
on my 'minimalistic' gentoo server, 442,000 on my slackware laptop, 
800,000 on a ubuntu server at work) it's not possible to do #1, so any 
deployed policy (especially one done by a disto that needs to work for all 
it's users) is going to follow #2, frequently to the point where it's not 
really adding much security.

David Lang


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  5:10                     ` Sean
@ 2007-06-09  5:38                       ` david
  2007-06-09  5:44                         ` Sean
  0 siblings, 1 reply; 240+ messages in thread
From: david @ 2007-06-09  5:38 UTC (permalink / raw)
  To: Sean; +Cc: Tetsuo Handa, linux-kernel, linux-security-module

On Sat, 9 Jun 2007, Sean wrote:

>>
>> the AA policy is also much easier to understand becouse you can look at it
>> in pieces, understand that piece, and then forget it and move on to the
>> next piece.
>
> Nobody is asking you to change the AA policy file.  It lives in user space.
> But i fail to see the problem in translating it into SELinux terms for
> the user transparently.



>> for example, if you write a policy for apache that limits it's access to
>> it's log files, install directories, and document root. then you write a
>> policy for your log analysis tool to access it's libraries, report
>> directories (under the apache document root) and the apache log files
>> (read only), these two policies are independant, you don't have to think
>> about one while creating the other (which you would have to do if you had
>> to put one label on apache binaries, another on normal web documents, a
>> third on the reports, a fourth on the log files, and a fifth on the
>> binaries for the log analysis tool. and this is ignoring any overlap in
>> libraries!)
>
> Again, try to think outside the box a bit.  This isn't about using SELinux
> as it exists today.  But imagine an SELinux that would ask you to
> supply a security label for each file _instead_ of looking up that label
> itself.  Wouldn't that let you implement everything you wanted while still
> using much of the SELinux infrastructure that is already in the kernel?

so are you suggesting that SELinux would call out to userspace for every 
file open to get the label for that file?

just off the top of my head

what would all these kernel->userspace->kernel transitions do to 
performance?

would SELinux give userspace the full path to that file?

if so wouldn't it have to implement most of what AA adds to do this?

if not how would userspace figure out what label to hand back without this 
info?

how would SELinux figure out the permissions for the userspace Daemon?

how would you change both the rules for labels in the kernel and the 
policy for assigning labels in userspace without any race conditions?

>> AA also lets a sysadmin dip their toe in the water and just write a policy
>> for Apache, not for anything else, then write a policy for firefox, then
>> write a policy for their mail client, then for bittorrent, etc. there is
>> no need or push to try and secure everything all at once, and no need to
>> re-label files (and change any policies that used the old labels) when
>> you discover a new interaction.
>
> And so it could remain;  this is about implementation, not model.

yes, you could add all the AA code to SELinux and then say that the result 
is implemented in SELinux, you may even save a little bit of code in some 
parts of it (but I would argue that you add more code in others, say for 
the userpace interface and userspace labeling code), but the result 
wouldn't be in the spirit of SELinux.

it may be possible to write something that resembles AA in SELinux policy 
(once you solve the problem of how to label newly created files securely), 
but it's also possible to write a webserver in COBOL to run out of inetd, 
that doesn't mean that it makes any sort of sense to do either one.

on the other hand, it may be a good idea. let's see how people really use 
AA once they have it available and the SELinux folks can work on 
duplicating the functionality, if they do then the existing AA interface 
could be phased out over time, or the internal implementation could 
change. but arguing that SELinux _may_ be able to do the job of AA 
_someday_ should not prevent AA from being included today (especially when 
so many of the SELinux developers are so opposed to the very concept of 
AA, which doesn't indicate that they are about to rush out and implement 
the pieces needed to make it work)

David Lang



^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  5:38                       ` david
@ 2007-06-09  5:44                         ` Sean
  2007-06-09  7:04                           ` david
  0 siblings, 1 reply; 240+ messages in thread
From: Sean @ 2007-06-09  5:44 UTC (permalink / raw)
  To: david; +Cc: Tetsuo Handa, linux-kernel, linux-security-module

On Fri, 8 Jun 2007 22:38:57 -0700 (PDT)
david@lang.hm wrote:


> so are you suggesting that SELinux would call out to userspace for every 
> file open to get the label for that file?
> 

No, i'm not.  You must already have a kernel function in the current
implementation of AA that decides the proper policy for each path.  Why
not use it  to feed labels into SELinux.

Sean

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  5:18             ` david
@ 2007-06-09  5:46               ` Sean
  2007-06-09  7:13                 ` david
  2007-06-09 16:18               ` Kyle Moffett
  2007-06-10 20:54               ` Crispin Cowan
  2 siblings, 1 reply; 240+ messages in thread
From: Sean @ 2007-06-09  5:46 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Fri, 8 Jun 2007 22:18:40 -0700 (PDT)
david@lang.hm wrote:

> the way I would describe the difference betwen AA and SELinux is:
> 
> SELinux is like a default allow IPS system, you have to describe 
> EVERYTHING to the system so that it knows what to allow and what to stop.
> 
> AA is like a default deny firewall, you describe what you want to happen, 
> and it blocks everything else without you even having to realize that it's 
> there.
> 
> now I know that this isn't a perfect analyogy, that SELinux doesn't allow 
> something to happen unless it's been told to let it, but in terms of 
> complexity and the amount of work to configure things I think the analogy 
> is close.

It must be drop dead simple to modify SELinux to be default-deny.  That
seems like it could be done in a small patch instead of requiring a huge
new infrastructure.

Let's assume that everyone agrees that AA is a good idea.  Which parts of it
absolutely can't be implemented in terms of SELinux?  SELinux isn't fixed in
stone, it can be altered if necessary to accommodate AA (as in the example
above of becoming default-deny).

Sean.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  5:44                         ` Sean
@ 2007-06-09  7:04                           ` david
  2007-06-09  7:28                             ` Sean
  0 siblings, 1 reply; 240+ messages in thread
From: david @ 2007-06-09  7:04 UTC (permalink / raw)
  To: Sean; +Cc: Tetsuo Handa, linux-kernel, linux-security-module

On Sat, 9 Jun 2007, Sean wrote:

>> so are you suggesting that SELinux would call out to userspace for every
>> file open to get the label for that file?
>>
>
> No, i'm not.  You must already have a kernel function in the current
> implementation of AA that decides the proper policy for each path.  Why
> not use it  to feed labels into SELinux.

if it was this easy just have SELinux set the label == path

you first need to figure out what the path is. right now this can't be 
done, the AA paches provide this capability.

second, the AA policies aren't based just on the path, they are based on 
the program accessing the path, then the path. you can have two different 
policies for two different programs accessing the same path, but for most 
programs (although, not nessasarily most activity) there will be no 
policy, and therefor no need to check the path.

but even if you did these things, why would it be an advantage to use a 
mechanism to create a dummy label and pass it off to different code rather 
then just decideing at that point? once the AA code knows what the policy 
for this path is for this program (which it would need to know to set the 
label) how is it a win to pass this off to another chunk of code? you 
would also need to make sure that the SELinux code didn't try to cache the 
label for future use either, becouse in the future the access may be from 
another program and so the policy that's needed is different.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  5:46               ` Sean
@ 2007-06-09  7:13                 ` david
  2007-06-09  7:36                   ` Sean
  2007-06-09 15:33                   ` Joshua Brindle
  0 siblings, 2 replies; 240+ messages in thread
From: david @ 2007-06-09  7:13 UTC (permalink / raw)
  To: Sean
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Sat, 9 Jun 2007, Sean wrote:

> On Fri, 8 Jun 2007 22:18:40 -0700 (PDT)
> david@lang.hm wrote:
>
>> the way I would describe the difference betwen AA and SELinux is:
>>
>> SELinux is like a default allow IPS system, you have to describe
>> EVERYTHING to the system so that it knows what to allow and what to stop.
>>
>> AA is like a default deny firewall, you describe what you want to happen,
>> and it blocks everything else without you even having to realize that it's
>> there.
>>
>> now I know that this isn't a perfect analyogy, that SELinux doesn't allow
>> something to happen unless it's been told to let it, but in terms of
>> complexity and the amount of work to configure things I think the analogy
>> is close.
>
> It must be drop dead simple to modify SELinux to be default-deny.  That
> seems like it could be done in a small patch instead of requiring a huge
> new infrastructure.

did you read my explination of the analogy?

> Let's assume that everyone agrees that AA is a good idea.  Which parts of it
> absolutely can't be implemented in terms of SELinux?  SELinux isn't fixed in
> stone, it can be altered if necessary to accommodate AA (as in the example
> above of becoming default-deny).

what SELinux cannot do is figure out what label to assign a new file.

but the bigger problem in changing SELinux to behave like AA is that the 
SELinux people disagree with the concept of AA. they don't believe that 
it's secure, so why would they add useless bloat that would only 
complicate their code and make systems less secure? I don't happen to 
agree with their opinion of AA obviously, but they have the right to their 
opinion, and it is their code. why should they be asked to implement and 
support something they disagree with so fundamentally?

remember that the security hooks in the kernel are not SELinux API's, they 
are the Loadable Security Model API. What the AA people are asking for is 
for the LSM API to be modified enough to let their code run (after that 
(and working in parallel) they will work on getting the rest of their code 
approved for the kernel, but the LSM hooks are the most critical)

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  7:04                           ` david
@ 2007-06-09  7:28                             ` Sean
  2007-06-09  8:03                               ` david
                                                 ` (2 more replies)
  0 siblings, 3 replies; 240+ messages in thread
From: Sean @ 2007-06-09  7:28 UTC (permalink / raw)
  To: david; +Cc: Tetsuo Handa, linux-kernel, linux-security-module

On Sat, 9 Jun 2007 00:04:15 -0700 (PDT)
david@lang.hm wrote:


> if it was this easy just have SELinux set the label == path
> you first need to figure out what the path is. right now this can't be 
> done, the AA paches provide this capability.

The question is: why not just extend SELinux to include AA functionality
rather than doing a whole new subsystem.  What exactly about AA demands
an entire new infrastructure rather than just building on what already
exists in the kernel?

> second, the AA policies aren't based just on the path, they are based on 
> the program accessing the path, then the path. you can have two different 
> policies for two different programs accessing the same path, but for most 
> programs (although, not nessasarily most activity) there will be no 
> policy, and therefor no need to check the path.

It seems the main purported advantage of AA is it doesn't require maintaining
labels on files etc.  In fact, that's the only conceptual difference I can
see other than a simpler policy file format.  So why not just make an AA
extension to SELinux that implements this main difference (ie. create labels
on the fly).

Then have a userspace program that converts the pretty-peace-and-love
AA policy file format into the baby-killing SELinux format and feed it
into the kernel.

All of a sudden you've implemented the main features of AA with very
few changes to the kernel.  It should be more maintainable, and much
easier to get accepted into the kernel.

> but even if you did these things, why would it be an advantage to use a 
> mechanism to create a dummy label and pass it off to different code rather 
> then just decideing at that point? 

Because it requires you to reimplement much of what is already in the kernel.
It requires you to be able to understand an entire new policy mechanism
instead of just piggybacking on what already exists.

> once the AA code knows what the policy 
> for this path is for this program (which it would need to know to set the 

Again you're only looking at the way the AA code is _today_.   If it were
refactored to be an extension of SELinux, there would be no reason for the
AA kernel code to know any policy whatsoever.   All it would need to know
is a path-to-label mapping.   SELinux would then enforce the AA policy
that it received from your userspace tool that translates your native
AA policy format into SELinux-lingo.

> label) how is it a win to pass this off to another chunk of code? you 

It's a win because the policy enforcement code is already in the kernel.
All you have to do is extend SELinux to create labels on the fly and provide
a userspace tool to convert the nice AA policy files into something SELinux
can use.

> would also need to make sure that the SELinux code didn't try to cache the 
> label for future use either, becouse in the future the access may be from 
> another program and so the policy that's needed is different.

You seem to be quibbling over small little unimportant details and refusing
to part with your current implementation.   It would seem the easiest way to
get the functionality you want into the kernel is to be a bit more flexible
on implementation.

Sean

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  7:13                 ` david
@ 2007-06-09  7:36                   ` Sean
  2007-06-09  8:06                     ` david
  2007-06-09 15:33                   ` Joshua Brindle
  1 sibling, 1 reply; 240+ messages in thread
From: Sean @ 2007-06-09  7:36 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Sat, 9 Jun 2007 00:13:22 -0700 (PDT)
david@lang.hm wrote:

> did you read my explination of the analogy?

It was a rather poor analogy i'm afraid.  But the point i make still stands.
So far you've failed to show any reason SELinux can't be reasonably extended
to handle all the features you care about.

> what SELinux cannot do is figure out what label to assign a new file.

That would be the job of your AA extension.

> but the bigger problem in changing SELinux to behave like AA is that the 
> SELinux people disagree with the concept of AA. they don't believe that 
> it's secure, so why would they add useless bloat that would only 
> complicate their code and make systems less secure? I don't happen to 
> agree with their opinion of AA obviously, but they have the right to their 
> opinion, and it is their code. why should they be asked to implement and 
> support something they disagree with so fundamentally?

So now you're claiming the real reason to let AA into the kernel is
politics? 

Just show that the feature can be easily added to SELinux and made as an
option for the end user to choose and it should go a long way to silencing
the opponents.

> 
> remember that the security hooks in the kernel are not SELinux API's, they 
> are the Loadable Security Model API. What the AA people are asking for is 
> for the LSM API to be modified enough to let their code run (after that 
> (and working in parallel) they will work on getting the rest of their code 
> approved for the kernel, but the LSM hooks are the most critical)

Remember that the SELinux API's essentially belong to everyone under the GPL.
So its not an excuse for falling into NIH syndrome and putting a bunch of
new stuff into the kernel that could instead be added as a small
extension to what already exists.

Sean


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  7:28                             ` Sean
@ 2007-06-09  8:03                               ` david
  2007-06-09  8:37                                 ` Sean
  2007-06-14 17:01                                 ` Pavel Machek
  2007-06-09 11:26                               ` [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching Tetsuo Handa
  2007-06-09 18:37                               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Casey Schaufler
  2 siblings, 2 replies; 240+ messages in thread
From: david @ 2007-06-09  8:03 UTC (permalink / raw)
  To: Sean; +Cc: Tetsuo Handa, linux-kernel, linux-security-module

On Sat, 9 Jun 2007, Sean wrote:

> On Sat, 9 Jun 2007 00:04:15 -0700 (PDT)
> david@lang.hm wrote:
>
>
>> if it was this easy just have SELinux set the label == path
>> you first need to figure out what the path is. right now this can't be
>> done, the AA paches provide this capability.
>
> The question is: why not just extend SELinux to include AA functionality
> rather than doing a whole new subsystem.  What exactly about AA demands
> an entire new infrastructure rather than just building on what already
> exists in the kernel?
>
>> second, the AA policies aren't based just on the path, they are based on
>> the program accessing the path, then the path. you can have two different
>> policies for two different programs accessing the same path, but for most
>> programs (although, not nessasarily most activity) there will be no
>> policy, and therefor no need to check the path.
>
> It seems the main purported advantage of AA is it doesn't require maintaining
> labels on files etc.  In fact, that's the only conceptual difference I can
> see other than a simpler policy file format.  So why not just make an AA
> extension to SELinux that implements this main difference (ie. create labels
> on the fly).

becouse the SELinux people don't want to have this in their code for one 
thing.

you seem to be ignoring the SELinux people who say that pathnames are 
fundamentally different from labels, labels stay with the data if the file 
is renamed, path names do not. multiple hard-links to the same file will 
always have the same label for SELinux, but could have very different 
permissions with AA

labels are part of policy, policy is not supposed to be decided by the 
kernel.

SELinux treats all files with the same label the same. to have the same 
ability to treat every file differntly that AA has SELinux would have to 
give every file a different label.


> Then have a userspace program that converts the pretty-peace-and-love
> AA policy file format into the baby-killing SELinux format and feed it
> into the kernel.
>
> All of a sudden you've implemented the main features of AA with very
> few changes to the kernel.  It should be more maintainable, and much
> easier to get accepted into the kernel.

how will you know how many labels you need to put into your policy that 
you load into the kernel?

how will the kernel figure out what label to use for a file

and the userspace code that converts the policy needs to know the names 
when it feeds the policy into the kernel.

and you still need to implement the new LSM hooks that AA is asking for to 
figure out what the path to a file is.

>> but even if you did these things, why would it be an advantage to use a
>> mechanism to create a dummy label and pass it off to different code rather
>> then just decideing at that point?
>
> Because it requires you to reimplement much of what is already in the kernel.
> It requires you to be able to understand an entire new policy mechanism
> instead of just piggybacking on what already exists.

the policy mechanism is supposed to be the LSM hooks, and AA is trying to 
re-use them.

>> once the AA code knows what the policy
>> for this path is for this program (which it would need to know to set the
>
> Again you're only looking at the way the AA code is _today_.   If it were
> refactored to be an extension of SELinux, there would be no reason for the
> AA kernel code to know any policy whatsoever.   All it would need to know
> is a path-to-label mapping.   SELinux would then enforce the AA policy
> that it received from your userspace tool that translates your native
> AA policy format into SELinux-lingo.

after you change SELinux to be able to do everything that AA does then you 
can tell SELinux to act like AA, true but irrelavent.

>> label) how is it a win to pass this off to another chunk of code? you
>
> It's a win because the policy enforcement code is already in the kernel.
> All you have to do is extend SELinux to create labels on the fly and provide
> a userspace tool to convert the nice AA policy files into something SELinux
> can use.
>
>> would also need to make sure that the SELinux code didn't try to cache the
>> label for future use either, becouse in the future the access may be from
>> another program and so the policy that's needed is different.
>
> You seem to be quibbling over small little unimportant details and refusing
> to part with your current implementation.   It would seem the easiest way to
> get the functionality you want into the kernel is to be a bit more flexible
> on implementation.

first off, and for the record, it's not _my_ implementation. I have 
nothing to do with writing AA.

I am just someone who manages hundreds of servers for which AA would be a 
good fit. In the past I've gone to a lot of effort to get less security 
then AA would provide to implement seperate services in seperate chroot 
sandboxes. I'm looking for easier and better options, I've looked at 
SELinux and don't believe that I can produce a reasonable policy in a 
reasonable amount of time (and I don't trust distro vendors to do it for 
me, they have to allow a lot of things that don't make sense on my 
systems, and I occasionally need to allow something that wouldn't make 
sense in the general case, let alone all the software I run that the disto 
doesn't know anything about)

chroot sandboxes, virtual machines, containers all have the problem that 
when you need to have more then one application interacting they need to 
be put togeather and the basic mechanism doesn't provide you any security 
against each other.

SELinux is aiming for 'perfect' security, I'll readily admit that, just 
like I'll admit that AA is only aiming for 'good enough' security, but 
that 'good enough' security would help me and I don't see any way to get 
to SELinux's 'perfect' security.

I also don't care about the details of how it gets implemented, but when 
the AA people have a working implementation, and the SELinux people are 
strongly opposed to the concept, I don't see any advantage in trying to 
get the AA people to throw away a lot of their working code to try and get 
people (many of who have be very insulting frankly) to accept such 
fandamental changes.

if the SELinux people had responded to the announcement of AA with "that's 
a nice idea, if we add these snippits from your code to SELinux then we 
can do the same thing" it would be a very different story.

but as always patches talk louder then anything else, if you believe that 
the efforts should be combined so strongly why don't you start submitting 
the appropriate patches to SELinux to make it able to do what AA does?

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  7:36                   ` Sean
@ 2007-06-09  8:06                     ` david
  2007-06-09  8:10                       ` Sean
  0 siblings, 1 reply; 240+ messages in thread
From: david @ 2007-06-09  8:06 UTC (permalink / raw)
  To: Sean
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Sat, 9 Jun 2007, Sean wrote:
>> remember that the security hooks in the kernel are not SELinux API's, they
>> are the Loadable Security Model API. What the AA people are asking for is
>> for the LSM API to be modified enough to let their code run (after that
>> (and working in parallel) they will work on getting the rest of their code
>> approved for the kernel, but the LSM hooks are the most critical)
>
> Remember that the SELinux API's essentially belong to everyone under the GPL.
> So its not an excuse for falling into NIH syndrome and putting a bunch of
> new stuff into the kernel that could instead be added as a small
> extension to what already exists.

but the SELinux API's are not the core security API's in Linux, the LSM 
API's are. and AA is useing the LSM API's (extending them where they and 
SELinux don't do what's needed)

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  8:06                     ` david
@ 2007-06-09  8:10                       ` Sean
  2007-06-09 15:17                         ` Andreas Gruenbacher
  0 siblings, 1 reply; 240+ messages in thread
From: Sean @ 2007-06-09  8:10 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Sat, 9 Jun 2007 01:06:09 -0700 (PDT)
david@lang.hm wrote:


> but the SELinux API's are not the core security API's in Linux, the LSM 
> API's are. and AA is useing the LSM API's (extending them where they and 
> SELinux don't do what's needed)
> 

Calling LSM "core" and pretending that SELinux can't do 90% of what you
want doesn't change the facts on the ground.  Clinging to the current AA
implementation instead of honestly considering reasonable alternatives
does not inspire confidence or teamwork.

Sean.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  8:03                               ` david
@ 2007-06-09  8:37                                 ` Sean
  2007-06-14 17:01                                 ` Pavel Machek
  1 sibling, 0 replies; 240+ messages in thread
From: Sean @ 2007-06-09  8:37 UTC (permalink / raw)
  To: david; +Cc: Tetsuo Handa, linux-kernel, linux-security-module

On Sat, 9 Jun 2007 01:03:15 -0700 (PDT)
david@lang.hm wrote:


> becouse the SELinux people don't want to have this in their code for one 
> thing.

Tuff nuggies to the SELinux people.. Show them code good enough they'd be
embarrassed to reject.

> you seem to be ignoring the SELinux people who say that pathnames are 
> fundamentally different from labels, labels stay with the data if the file 
> is renamed, path names do not. multiple hard-links to the same file will 
> always have the same label for SELinux, but could have very different 
> permissions with AA
>
> labels are part of policy, policy is not supposed to be decided by the 
> kernel.

Not sure why you're rehashing this.  We all know that not everyone
agrees with AA.  The point is users should have a choice.. choice is
good.  But that's not a justification for bloating the kernel with
a bunch of code that isn't needed and can be refactored into a
small extension of what already exists.

> SELinux treats all files with the same label the same. to have the same 
> ability to treat every file differntly that AA has SELinux would have to 
> give every file a different label.

I'm not convinced in practice you really need a unique label for every
file.  Large swathes of the system would have a shared label etc..  So
let's not get caught up on theoretical arguments that don't really play
in practice.  Has anyone on the AA team actually _tried_ to extend
SELinux instead of reinventing the wheel?
 
> how will you know how many labels you need to put into your policy that 
> you load into the kernel?
> 
> how will the kernel figure out what label to use for a file

The AA extension will have a path-to-label mapping.  Conceptually that's
exactly what its doing now.  Look at the arguments by AA proponents that
the only difference between the AA method and SELinux is _when_ those
labels are created...  Sorry i don't have a link handy, but i can dig one
up if you dispute that this argument has been made by the AA folks.

> and the userspace code that converts the policy needs to know the names 
> when it feeds the policy into the kernel.
> and you still need to implement the new LSM hooks that AA is asking for to 
> figure out what the path to a file is.

True, but so what?

> the policy mechanism is supposed to be the LSM hooks, and AA is trying to 
> re-use them.

Who says that's what is "supposed" to be in all situations?   It makes more
sense to target the best API that lets you implement the features you want.

> after you change SELinux to be able to do everything that AA does then you 
> can tell SELinux to act like AA, true but irrelavent.

BS.  All we're talking about is an extension that allows SELinux to
generate labels on the fly.   That goes most the way towards giving
you all the functionality you're after and should be a much smaller patch
in the end, reusing code that already exists in the kernel.

> first off, and for the record, it's not _my_ implementation. I have 
> nothing to do with writing AA.
> 
> I am just someone who manages hundreds of servers for which AA would be a 
> good fit. In the past I've gone to a lot of effort to get less security 
> then AA would provide to implement seperate services in seperate chroot 
> sandboxes. I'm looking for easier and better options, I've looked at 
> SELinux and don't believe that I can produce a reasonable policy in a 
> reasonable amount of time (and I don't trust distro vendors to do it for 
> me, they have to allow a lot of things that don't make sense on my 
> systems, and I occasionally need to allow something that wouldn't make 
> sense in the general case, let alone all the software I run that the disto 
> doesn't know anything about)

Whoa.  Again you're mistaking the current state of SELinux, rather than
SELinux + AA extension.   If such a beast provides the same features you
get with the current AA implementation, why would you care?

> chroot sandboxes, virtual machines, containers all have the problem that 
> when you need to have more then one application interacting they need to 
> be put togeather and the basic mechanism doesn't provide you any security 
> against each other.
>
> SELinux is aiming for 'perfect' security, I'll readily admit that, just 
> like I'll admit that AA is only aiming for 'good enough' security, but 
> that 'good enough' security would help me and I don't see any way to get 
> to SELinux's 'perfect' security.

All that is irrelevant to the discussion though.

> Also don't care about the details of how it gets implemented, but when 
> the AA people have a working implementation, and the SELinux people are 
> strongly opposed to the concept, I don't see any advantage in trying to 
> get the AA people to throw away a lot of their working code to try and get 
> people (many of who have be very insulting frankly) to accept such 
> fandamental changes.

But "working implementation" is _not_ the criteria for acceptance into
the kernel and that's what this discussion is about.

> if the SELinux people had responded to the announcement of AA with "that's 
> a nice idea, if we add these snippits from your code to SELinux then we 
> can do the same thing" it would be a very different story.

To be fair, that's not their job.
 
> but as always patches talk louder then anything else, if you believe that 
> the efforts should be combined so strongly why don't you start submitting 
> the appropriate patches to SELinux to make it able to do what AA does?

Because i'm not the one trying to get something into the kernel.  I'm not
the one who has to show that my patches are reasonable and make best use
of the current kernel infrastructure possible.

Sean

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching
  2007-06-09  7:28                             ` Sean
  2007-06-09  8:03                               ` david
@ 2007-06-09 11:26                               ` Tetsuo Handa
  2007-06-09 11:35                                 ` Sean
  2007-06-09 18:37                               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Casey Schaufler
  2 siblings, 1 reply; 240+ messages in thread
From: Tetsuo Handa @ 2007-06-09 11:26 UTC (permalink / raw)
  To: seanlkml; +Cc: linux-kernel, linux-security-module


Sean wrote:
> All of a sudden you've implemented the main features of AA with very
> few changes to the kernel.  It should be more maintainable, and much
> easier to get accepted into the kernel.
Do you agree with passing "struct vfsmount" to VFS helper functions and LSM hooks
and introducing d_namespace_path() so that the AA extension can calculate the requested pathname
and map the requested pathname to SELinux's labels?

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching
  2007-06-09 11:26                               ` [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching Tetsuo Handa
@ 2007-06-09 11:35                                 ` Sean
  2007-06-09 13:41                                   ` david
  0 siblings, 1 reply; 240+ messages in thread
From: Sean @ 2007-06-09 11:35 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: linux-kernel, linux-security-module

On Sat, 9 Jun 2007 20:26:57 +0900
Tetsuo Handa <from-lsm@I-love.SAKURA.ne.jp> wrote:

> Sean wrote:
> > All of a sudden you've implemented the main features of AA with very
> > few changes to the kernel.  It should be more maintainable, and much
> > easier to get accepted into the kernel.
> Do you agree with passing "struct vfsmount" to VFS helper functions and LSM hooks
> and introducing d_namespace_path() so that the AA extension can calculate the requested pathname
> and map the requested pathname to SELinux's labels?
> 

Frankly i'm not in a position to judge, but if that's the best way to provide
the desired functionality, then it sounds good.  But please make sure you
bounce this all off someone who actually knows what they're talking about. ;o)
Really I was just casually following along this ongoing conversation and had
a more conceptual/design question about how things were implemented.  A few
people explained how AA labelling at "runtime" wasn't conceptually very
different than what SELinux did.  All that begged the question as to why 
that functionality couldn't just be tacked on to SELinux?

Sean

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-04 14:30                 ` Andreas Gruenbacher
  2007-06-06 13:09                   ` Stephen Smalley
@ 2007-06-09 12:58                   ` Pavel Machek
  2007-06-09 13:44                     ` Andreas Gruenbacher
  1 sibling, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-06-09 12:58 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

Hi!

> > How will kernel work with very long paths? I'd suspect some problems,
> > if path is 1MB long and I attempt to print it in /proc
> > somewhere.
> 
> Pathnames are only used for informational purposes in the kernel, except in 
> AppArmor of course. /proc only uses pathnames in a few places, 
> but /proc/mounts will silently fail and produce garbage entries. That's not 
> ideal of course; we should fix that somehow.

> Note that this has nothing to do with the AppArmor discussion ...

This has everything to do with AA discussion. You took unreliable,
for-user-info kernel subsystem, and made security subsystem depend on
it. Oops.

> > Perhaps vfs should be modified not to allow such crazy paths? But placing
> > limit in aa is ugly. 
> 
> Dream on. Redefining fundamental vfs semantics is not an option; we should 
> rather make sure that we fail gracefully. Considering the

And instead of fixing "too long pathnames are problem in kernel" in
any clean way, you "simply" included
configurable-but-impossible-to-configure-right limit into
apparmor. And now you want that merged. Dream on.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching
  2007-06-09 11:35                                 ` Sean
@ 2007-06-09 13:41                                   ` david
  0 siblings, 0 replies; 240+ messages in thread
From: david @ 2007-06-09 13:41 UTC (permalink / raw)
  To: Sean; +Cc: Tetsuo Handa, linux-kernel, linux-security-module

On Sat, 9 Jun 2007, Sean wrote:

> On Sat, 9 Jun 2007 20:26:57 +0900
> Tetsuo Handa <from-lsm@I-love.SAKURA.ne.jp> wrote:
>
>> Sean wrote:
>>> All of a sudden you've implemented the main features of AA with very
>>> few changes to the kernel.  It should be more maintainable, and much
>>> easier to get accepted into the kernel.
>> Do you agree with passing "struct vfsmount" to VFS helper functions and LSM hooks
>> and introducing d_namespace_path() so that the AA extension can calculate the requested pathname
>> and map the requested pathname to SELinux's labels?
>>
>
> Frankly i'm not in a position to judge, but if that's the best way to provide
> the desired functionality, then it sounds good.  But please make sure you
> bounce this all off someone who actually knows what they're talking about. ;o)
> Really I was just casually following along this ongoing conversation and had
> a more conceptual/design question about how things were implemented.  A few
> people explained how AA labelling at "runtime" wasn't conceptually very
> different than what SELinux did.  All that begged the question as to why
> that functionality couldn't just be tacked on to SELinux?

Sean,
   since you aren't in a position to judge what's acceptable and I'm not in 
a position to change code our exchange is pointless.

I apologize to the list for the excessive messasges.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-09 12:58                   ` Pavel Machek
@ 2007-06-09 13:44                     ` Andreas Gruenbacher
  2007-06-12 13:06                       ` Pavel Machek
  0 siblings, 1 reply; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-09 13:44 UTC (permalink / raw)
  To: Pavel Machek
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Saturday 09 June 2007 14:58, Pavel Machek wrote:
> > > How will kernel work with very long paths? I'd suspect some problems,
> > > if path is 1MB long and I attempt to print it in /proc
> > > somewhere.
> > 
> > Pathnames are only used for informational purposes in the kernel, except 
> > in AppArmor of course. /proc only uses pathnames in a few places, 
> > but /proc/mounts will silently fail and produce garbage entries. That's 
> > not ideal of course; we should fix that somehow.
> 
> > Note that this has nothing to do with the AppArmor discussion ...
> 
> This has everything to do with AA discussion.

How pathnames are used in /proc has *nothing* to do with AppAmor.

> You took unreliable, for-user-info kernel subsystem, and made security
> subsystem depend on it. Oops.

Wrong. I said that the kernel uses pathnames for informational purposes only, 
not that they are unreliable. Don't turn words around in my mouth. The dcache 
has a *very* precise idea of pathnames, because this is what it is there for.

The pathnames that d_path computes exactly reflect what the dcache knows. 
(This requires the d_path fixes that are included in the AppArmor series and 
have also been posted independently, and the reasons why these fixes are 
needed are well explained in the mails.) The resulting pathnames are anything 
but unreliable.

> > > Perhaps vfs should be modified not to allow such crazy paths? But 
> > > placing limit in aa is ugly. 
> > 
> > Dream on. Redefining fundamental vfs semantics is not an option; we should 
> > rather make sure that we fail gracefully. Considering the
> 
> And instead of fixing "too long pathnames are problem in kernel" in any
> clean way, you "simply" included
> configurable-but-impossible-to-configure-right limit into
> apparmor. And now you want that merged. Dream on.

The choice here is between the following two things: either allow pathnames to 
grow to arbitrary lengths, or cap them at some point. The former has the 
benefit of working with all possible pathnames, and the drawback that users 
can consume arbitrary amounts of kernel memory by constructing arbitrarily 
long paths.

The latter has the benefit of limiting the amount of kernel memory consumed to 
some upper bound, and the drawback that access to exceptionally long paths 
(beyond the arbitrary limit) is denied. So in a sense, the limit in AppArmor 
does what you are asking for: it modifies things so that the kernel does not 
allow "such crazy paths". It does not introduce this as a vfs limit though, 
because the vfs has all right not to care.

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  0:17           ` Greg KH
  2007-06-09  1:06             ` david
  2007-06-09  5:18             ` david
@ 2007-06-09 15:05             ` Andreas Gruenbacher
  2007-06-10 17:09             ` Crispin Cowan
  3 siblings, 0 replies; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-09 15:05 UTC (permalink / raw)
  To: Greg KH
  Cc: Stephen Smalley, Pavel Machek, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Saturday 09 June 2007 02:17, Greg KH wrote:
> On Sat, Jun 09, 2007 at 12:03:57AM +0200, Andreas Gruenbacher wrote:
> > AppArmor is meant to be relatively easy to understand, manage, and
> >  customize, and introducing a labels layer wouldn't help these goals.
> 
> Woah, that describes the userspace side of AA just fine, it means
> nothing when it comes to the in-kernel implementation. There is no 
> reason that you can't implement the same functionality using some
> totally different in-kernel solution if possible.

I agree that the in-kernel implementation could use different abstractions 
than user-space, provided that the underlying implementation details can be 
hidden well enough. The key phrase here is "if possible", and in fact "if 
possible" is much too strong: very many things in software are possible, 
including user-space drives and a stable kernel module ABI. Some things make 
sense; others are genuinely bad ideas while still possible.

The things in my reply you chose not to quote make up the essential part of 
the model, argue why mapping from an AppArmor-like user-space to a 
label-based in-kernel model is fundamentally hard, how implementation details 
cannot be hidden, and how such a mapping would lead to disadvantages no 
matter which way you look at it.

> > SELinux is applicable in areas where AppArmor is not (e.g., MLS), but
> > this comes at a cost. For me the question is not SELinux or AppArmor,
> > but if AppArmor's security model is a good solution in common
> > scenarios. In my opinion, AppArmor is a better answer than SELinux in
> > a number of scenarios. This gives it value, nonwithstanding the fact
> > that SELinux can be taken further.
> 
> I am still not completely certian that we can not properly implement AA
> functionality using a SELinux backend solution.  Yes, the current tools
> that try to implement this are still lacking, and maybe the kernel needs
> to change, but that is possible.

I did not pull all of this out of my hat ad hoc. The AppArmor team spent a 
fair amount of time researching various ways how AppArmor-like semantics 
could be implemented on top of SELinux, as well as ways how AppArmor could be 
implemented better. We *really* tried hard. The reason why we are still 
proposing this non-SELinux approach is because none of the alternatives 
worked out.

If things were as simple as mapping an AppArmor frontend to the SELinux 
backend, even with extensions to the SELinux backend (and I know that it 
wouldn't be impossible to extend SELinux in reasonable ways), this would 
indeed be nice. The issues that SEEdit is having unfortunately only confirm 
what we were already certain to know: it just doesn't work.

> I still want to see a definition of the AA "model" that we can then use
> to try to implement using whatever solution works best.  As that seems
> to be missing the current argument of if AA can or can not be
> implemented using SELinux or something totally different should be
> stopped.

There is no need to start all over implementing something from scratch. People 
have already tried emulating AppArmor on top of SELinux, and SEEdit is the 
current best result. All it takes is the time to understand the SELinux and 
AppArmor models. From there it is not hard to see that SEEdit does the best 
it can do, and how it is just not a good idea. There are a few things that 
could be improved with additional SELinux in-kernel infrastructure, but the 
fundamental problems remain. It just remains a very bad idea.

> So, AA developers, do you have such a document anywhere?  I know there
> are some old research papers, do they properly describe the current
> model you are trying to implement here?

We wrote an AppArmor technical documentation, and it was posted as part of the 
last two AppArmor submissions. It describes the model, and how the model is 
implemented. If you need a better description of the model, let us know how 
we can improve it.

  http://forgeftp.novell.com//apparmor/LKML_Submission-May_07/techdoc.pdf

What you'll not find in there is a detailed comparison between AppArmor and 
SELinux, and the problems that emulating AppArmor on top of SELinux would 
cause -- some details on that can be found in the SEEdit documentation, and 
in addition, this LKML thread seems best to me at the moment.

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  8:10                       ` Sean
@ 2007-06-09 15:17                         ` Andreas Gruenbacher
  2007-06-09 16:36                           ` Sean
  0 siblings, 1 reply; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-09 15:17 UTC (permalink / raw)
  To: Sean
  Cc: david, Greg KH, Stephen Smalley, Pavel Machek, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Saturday 09 June 2007 10:10, Sean wrote:
> Clinging to the current AA implementation instead of honestly considering
> reasonable alternatives does not inspire confidence or teamwork.

What you imply is pretty insulting. I can assure you we looked into many 
possible implementation choices, and we considered a fair number of 
alternatives.

Have you seen the ``AppArmor FAQ'' thread?

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  7:13                 ` david
  2007-06-09  7:36                   ` Sean
@ 2007-06-09 15:33                   ` Joshua Brindle
  1 sibling, 0 replies; 240+ messages in thread
From: Joshua Brindle @ 2007-06-09 15:33 UTC (permalink / raw)
  To: david
  Cc: Sean, Greg KH, Andreas Gruenbacher, Stephen Smalley,
	Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

david@lang.hm wrote:
> On Sat, 9 Jun 2007, Sean wrote:
> <snip>
>
> what SELinux cannot do is figure out what label to assign a new file.
>

Nit: SELinux figures out what to label new files fine, just not based on 
the name. This works in most cases, eg., when user_t creates a file in 
/tmp it becomes user_tmp_t, incidentally this is something that AA 
cannot handle, if the filenames aren't normalized (they normally 
aren't). For example, my ssh agent socket is stored in 
/tmp/ssh-XXXXXXXX, where the X's are random characters, AA can't 
differentiate admin ssh agents from unprivileged user ssh agents, 
showing a serious flaw in their model.

The complaint is that name-based labeling doesn't currently exist (and 
as Sean has stated that doesn't mean it _can't_ exist, just that it 
doesn't currently). In practice this has not been as big of an issue as 
you are making it out to be. Granted restorecond has a tiny race, and I 
wouldn't recommend using it on very security sensitive files but for 
usability having it relabel user_home_t to user_http_content_t isn't a 
problem (and causes no security issues).


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  5:18             ` david
  2007-06-09  5:46               ` Sean
@ 2007-06-09 16:18               ` Kyle Moffett
  2007-06-09 16:46                 ` david
  2007-06-10 20:54               ` Crispin Cowan
  2 siblings, 1 reply; 240+ messages in thread
From: Kyle Moffett @ 2007-06-09 16:18 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Jun 09, 2007, at 01:18:40, david@lang.hm wrote:
> SELinux is like a default allow IPS system, you have to describe  
> EVERYTHING to the system so that it knows what to allow and what to  
> stop.

WRONG.  You clearly don't understand SELinux at all.  Try booting in  
enforcing mode with an empty policy file (well, not quite empty,  
there are a few mandatory labels you have to create before it's a  
valid policy file).  /sbin/init will load the initial policy, attempt  
to re-exec() itself... and promptly grind to a halt.  End-of-story.

Typical "targetted" policies leave all user logins as unrestricted,  
adding security for daemons but not getting in the way of users who  
would otherwise turn SELinux off.  On the other hand, a targeted  
policy has a "trusted" type for user logins which is explicitly  
allowed access to everything.

That said, if you actually want your system to *work* with any  
default-deny policy then you have to describe EVERYTHING anyways.   
How exactly do you expect AppArmor to "work" if you don't allow users  
to run "/bin/passwd", for example.

Cheers,
Kyle Moffett


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09 15:17                         ` Andreas Gruenbacher
@ 2007-06-09 16:36                           ` Sean
  0 siblings, 0 replies; 240+ messages in thread
From: Sean @ 2007-06-09 16:36 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: david, Greg KH, Stephen Smalley, Pavel Machek, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Sat, 9 Jun 2007 17:17:57 +0200
Andreas Gruenbacher <agruen@suse.de> wrote:

> On Saturday 09 June 2007 10:10, Sean wrote:
> > Clinging to the current AA implementation instead of honestly considering
> > reasonable alternatives does not inspire confidence or teamwork.
> 
> What you imply is pretty insulting. I can assure you we looked into many 
> possible implementation choices, and we considered a fair number of 
> alternatives.

Sorry for any unintended insult.  The comment was meant solely for the person
with whom i was talking who seemed only to be cheerleading for inclusion
in current form without being willing or able to discuss alternative
implementations.

Sean.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09 16:18               ` Kyle Moffett
@ 2007-06-09 16:46                 ` david
  2007-06-09 17:06                   ` Kyle Moffett
  0 siblings, 1 reply; 240+ messages in thread
From: david @ 2007-06-09 16:46 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Sat, 9 Jun 2007, Kyle Moffett wrote:

> On Jun 09, 2007, at 01:18:40, david@lang.hm wrote:
>> SELinux is like a default allow IPS system, you have to describe EVERYTHING 
>> to the system so that it knows what to allow and what to stop.
>
> WRONG.  You clearly don't understand SELinux at all.  Try booting in 
> enforcing mode with an empty policy file (well, not quite empty, there are a 
> few mandatory labels you have to create before it's a valid policy file). 
> /sbin/init will load the initial policy, attempt to re-exec() itself... and 
> promptly grind to a halt.  End-of-story.

sigh,
   two paragraphs below what you quoted I acknowledged exactly what you 
state. however since you must tag everything before you turn on any 
security it seems to me that you have to define everything, which is a 
similar amount of work as you would have to do for a default allow policy.

> Typical "targetted" policies leave all user logins as unrestricted, adding 
> security for daemons but not getting in the way of users who would otherwise 
> turn SELinux off.  On the other hand, a targeted policy has a "trusted" type 
> for user logins which is explicitly allowed access to everything.

Ok, it sounds as if I did misunderstand SELinux. I thought that by 
labeling the individual files you couldn't do the 'only restrict apache' 
type of thing.

> That said, if you actually want your system to *work* with any default-deny 
> policy then you have to describe EVERYTHING anyways.  How exactly do you 
> expect AppArmor to "work" if you don't allow users to run "/bin/passwd", for 
> example.

for AA you don't try to define permissions for every executable, and ones 
that you don't define policy are unrestricted.

so as I understand this with SELinux you will have lots of labels around 
your system (more as you lock down the system more) you need to define 
policy so that your unrestricted users must have access to every label, 
and every time you create a new label you need to go back to all your 
policies to see if the new label needs to be allowed from that policy

is this correct?

David Lang


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09 16:46                 ` david
@ 2007-06-09 17:06                   ` Kyle Moffett
  2007-06-09 17:32                     ` david
  0 siblings, 1 reply; 240+ messages in thread
From: Kyle Moffett @ 2007-06-09 17:06 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Jun 09, 2007, at 12:46:40, david@lang.hm wrote:
> On Sat, 9 Jun 2007, Kyle Moffett wrote:
>> Typical "targetted" policies leave all user logins as  
>> unrestricted, adding security for daemons but not getting in the  
>> way of users who would otherwise turn SELinux off.  On the other  
>> hand, a targeted policy has a "trusted" type for user logins which  
>> is explicitly allowed access to everything.
>
> Ok, it sounds as if I did misunderstand SELinux. I thought that by  
> labeling the individual files you couldn't do the 'only restrict  
> apache' type of thing.
>
>> That said, if you actually want your system to *work* with any  
>> default-deny policy then you have to describe EVERYTHING anyways.   
>> How exactly do you expect AppArmor to "work" if you don't allow  
>> users to run "/bin/passwd", for example.
>
> for AA you don't try to define permissions for every executable,  
> and ones that you don't define policy are unrestricted.
>
> so as I understand this with SELinux you will have lots of labels  
> around your system (more as you lock down the system more) you need  
> to define policy so that your unrestricted users must have access  
> to every label, and every time you create a new label you need to  
> go back to all your policies to see if the new label needs to be  
> allowed from that policy

Actually, it's easier than that.  There are type attributes which may  
be assigned to an arbitrary set of types, and each "type" field in an  
access rule may use either a type or an attribute.  So you don't  
actually need to modify existing rules when adding new types, you  
just add the appropriate existing attributes to your new type.  For  
example, you could set up a "logfile" attribute which allows  
logrotate to archive old versions and allows audit-admin users to  
modify/delete them, then whenever you need to add a new logfile you  
just declare the "my_foo_log_t" type to have the "logfile" attribute.

On the other hand, I seem to recall that typical "targeted" policies  
don't grant most of the additional access via access rules, they  
instead add a special case to the fundamental "constraints" in the  
policy (IE: If the subject type has the "trusted" attribute then skip  
some of the other type-based checks).

Cheers,
Kyle Moffett


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09 17:06                   ` Kyle Moffett
@ 2007-06-09 17:32                     ` david
  2007-06-09 19:50                       ` Kyle Moffett
  0 siblings, 1 reply; 240+ messages in thread
From: david @ 2007-06-09 17:32 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Sat, 9 Jun 2007, Kyle Moffett wrote:

> On Jun 09, 2007, at 12:46:40, david@lang.hm wrote:
>> On Sat, 9 Jun 2007, Kyle Moffett wrote:
>> > Typical "targetted" policies leave all user logins as unrestricted, 
>> > adding security for daemons but not getting in the way of users who would 
>> > otherwise turn SELinux off.  On the other hand, a targeted policy has a 
>> > "trusted" type for user logins which is explicitly allowed access to 
>> > everything.
>> 
>> Ok, it sounds as if I did misunderstand SELinux. I thought that by labeling 
>> the individual files you couldn't do the 'only restrict apache' type of 
>> thing.
>> 
>> > That said, if you actually want your system to *work* with any 
>> > default-deny policy then you have to describe EVERYTHING anyways.  How 
>> > exactly do you expect AppArmor to "work" if you don't allow users to run 
>> > "/bin/passwd", for example.
>> 
>> for AA you don't try to define permissions for every executable, and ones 
>> that you don't define policy are unrestricted.
>> 
>> so as I understand this with SELinux you will have lots of labels around 
>> your system (more as you lock down the system more) you need to define 
>> policy so that your unrestricted users must have access to every label, and 
>> every time you create a new label you need to go back to all your policies 
>> to see if the new label needs to be allowed from that policy
>
> Actually, it's easier than that.  There are type attributes which may be 
> assigned to an arbitrary set of types, and each "type" field in an access 
> rule may use either a type or an attribute.  So you don't actually need to 
> modify existing rules when adding new types, you just add the appropriate 
> existing attributes to your new type.  For example, you could set up a 
> "logfile" attribute which allows logrotate to archive old versions and allows 
> audit-admin users to modify/delete them, then whenever you need to add a new 
> logfile you just declare the "my_foo_log_t" type to have the "logfile" 
> attribute.

isn't this just the flip side of the same problem?

every time you define a new attribute you need to go through all the files 
and decide if the new attribute needs to be given to that file.

David Lang

> On the other hand, I seem to recall that typical "targeted" policies don't 
> grant most of the additional access via access rules, they instead add a 
> special case to the fundamental "constraints" in the policy (IE: If the 
> subject type has the "trusted" attribute then skip some of the other 
> type-based checks).
>
> Cheers,
> Kyle Moffett
>
>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  7:28                             ` Sean
  2007-06-09  8:03                               ` david
  2007-06-09 11:26                               ` [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching Tetsuo Handa
@ 2007-06-09 18:37                               ` Casey Schaufler
  2007-06-15 13:36                                 ` Pavel Machek
  2 siblings, 1 reply; 240+ messages in thread
From: Casey Schaufler @ 2007-06-09 18:37 UTC (permalink / raw)
  To: Sean, david; +Cc: Tetsuo Handa, linux-kernel, linux-security-module


--- Sean <seanlkml@sympatico.ca> wrote:


> The question is: why not just extend SELinux to include AA functionality
> rather than doing a whole new subsystem.

Because, as hard as it seems for some people to believe,
not everyone wants Type Enforcement. SELinux is a fine
implementation of type enforcement, but if you don't want
what it does it would be silly to require that it be
used in order to accomplish something else, like name based
access control.

If the same things made everyone feel "secure" there would be
no optional security facilities (audit, cryptfs, /dev/random, ACLs).
It appears that the AA folks are sufficiently unimpressed with
SELinux they want to do something different. I understand that
there is a contingent that believes security == SELinux. 
There are also people who believe security == cryptography or
security == virus scanners. I'm happy that they have found what
works for them.

Also, "just extend" implies that it would be easy to do. I
suggest you go read the SELinux MLS code, and go read some
of the discussions about getting MLS working for the RedHat LSP
before you go throwing "just" around.


Casey Schaufler
casey@schaufler-ca.com

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09 17:32                     ` david
@ 2007-06-09 19:50                       ` Kyle Moffett
  2007-06-09 20:43                         ` david
  0 siblings, 1 reply; 240+ messages in thread
From: Kyle Moffett @ 2007-06-09 19:50 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Jun 09, 2007, at 13:32:05, david@lang.hm wrote:
> On Sat, 9 Jun 2007, Kyle Moffett wrote:
>> On Jun 09, 2007, at 12:46:40, david@lang.hm wrote:
>>> so as I understand this with SELinux you will have lots of labels  
>>> around your system (more as you lock down the system more) you  
>>> need to define policy so that your unrestricted users must have  
>>> access to every label, and every time you create a new label you  
>>> need to go back to all your policies to see if the new label  
>>> needs to be allowed from that policy
>>
>> Actually, it's easier than that.  There are type attributes which  
>> may be assigned to an arbitrary set of types, and each "type"  
>> field in an access rule may use either a type or an attribute.  So  
>> you don't actually need to modify existing rules when adding new  
>> types, you just add the appropriate existing attributes to your  
>> new type.  For example, you could set up a "logfile" attribute  
>> which allows logrotate to archive old versions and allows audit- 
>> admin users to modify/delete them, then whenever you need to add a  
>> new logfile you just declare the "my_foo_log_t" type to have the  
>> "logfile" attribute.
>
> isn't this just the flip side of the same problem?
>
> every time you define a new attribute you need to go through all  
> the files and decide if the new attribute needs to be given to that  
> file.

No you don't, you can add attributes to a type after-the-fact.  In  
concept this problem is very similar to programming:  You have  
various documented interfaces used by different policy files to  
interact with each other.  As long as your policy files conform to  
the documented interfaces then you *DONT* have to manually inspect  
each file because you can make basic assumptions.  On the other hand,  
when you break that interface "contract" you will get very unexpected  
results.  For the above example:

My syslog policy file would create a "logfile" attribute and types  
for "/var/log/auth/auth.log", "/var/log/kern/kern.log", and "/var/log/ 
messages".  It would also create a "logdaemon" attribute which has  
automatic type transitions to create files in different "/var/log/*"  
directories  Finally, it would allow the syslogd type to create and  
append to its specific file types for "auth.log", "kern.log", and  
"messages".

My logrotate policy file would depend on the syslog policy and would  
declare the logrotate daemon type as a "logdaemon", and additionally  
allow logrotate to read, rename, append, and delete "logfile" types.   
Since logrotate is a "logdaemon", it already has the appropriate type  
transitions for new types.

My samba policy file would depend on the syslog policy and would  
declare the samba daemon type as a "logdaemon" and the "/var/log/ 
samba/*" type as a "logfile".  Then it would add a type transition  
rule so when "logdaemon" creates new files in "samba_log_dir_t", they  
have the appropriate "samba_log_t" label.  Finally, samba would allow  
itself to append to "samba_log_t" files.

Note that now when "logrotate" runs and rotates files in /var/log/ 
samba, it will automatically create the new files with type  
"samba_log_t", even though there are no *direct* associations between  
those types.  If the syslog policy file was poorly written it could  
seriously adversely affect the security of the system, but hopefully  
that's obvious :-D.  Policy development is _hard_, it's a whole  
separate state-machine and pseudo-programming-language that should  
mostly be left to security professionals or very experienced  
developers/sysadmins.

Cheers,
Kyle Moffett


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09 19:50                       ` Kyle Moffett
@ 2007-06-09 20:43                         ` david
  0 siblings, 0 replies; 240+ messages in thread
From: david @ 2007-06-09 20:43 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Sat, 9 Jun 2007, Kyle Moffett wrote:

> On Jun 09, 2007, at 13:32:05, david@lang.hm wrote:
>> On Sat, 9 Jun 2007, Kyle Moffett wrote:
>> > On Jun 09, 2007, at 12:46:40, david@lang.hm wrote:
>> > > so as I understand this with SELinux you will have lots of labels 
>> > > around your system (more as you lock down the system more) you need to 
>> > > define policy so that your unrestricted users must have access to every 
>> > > label, and every time you create a new label you need to go back to all 
>> > > your policies to see if the new label needs to be allowed from that 
>> > > policy
>> > 
>> > Actually, it's easier than that.  There are type attributes which may be 
>> > assigned to an arbitrary set of types, and each "type" field in an access 
>> > rule may use either a type or an attribute.  So you don't actually need 
>> > to modify existing rules when adding new types, you just add the 
>> > appropriate existing attributes to your new type.  For example, you could 
>> > set up a "logfile" attribute which allows logrotate to archive old 
>> > versions and allows audit-admin users to modify/delete them, then 
>> > whenever you need to add a new logfile you just declare the 
>> > "my_foo_log_t" type to have the "logfile" attribute.
>> 
>> isn't this just the flip side of the same problem?
>> 
>> every time you define a new attribute you need to go through all the files 
>> and decide if the new attribute needs to be given to that file.
>
> No you don't, you can add attributes to a type after-the-fact.  In concept 
> this problem is very similar to programming:  You have various documented 
> interfaces used by different policy files to interact with each other.  As 
> long as your policy files conform to the documented interfaces then you 
> *DONT* have to manually inspect each file because you can make basic 
> assumptions.  On the other hand, when you break that interface "contract" you 
> will get very unexpected results.  For the above example:
>
> My syslog policy file would create a "logfile" attribute and types for 
> "/var/log/auth/auth.log", "/var/log/kern/kern.log", and "/var/log/messages". 
> It would also create a "logdaemon" attribute which has automatic type 
> transitions to create files in different "/var/log/*" directories  Finally, 
> it would allow the syslogd type to create and append to its specific file 
> types for "auth.log", "kern.log", and "messages".
>
> My logrotate policy file would depend on the syslog policy and would declare 
> the logrotate daemon type as a "logdaemon", and additionally allow logrotate 
> to read, rename, append, and delete "logfile" types.  Since logrotate is a 
> "logdaemon", it already has the appropriate type transitions for new types.
>
> My samba policy file would depend on the syslog policy and would declare the 
> samba daemon type as a "logdaemon" and the "/var/log/samba/*" type as a 
> "logfile".  Then it would add a type transition rule so when "logdaemon" 
> creates new files in "samba_log_dir_t", they have the appropriate 
> "samba_log_t" label.  Finally, samba would allow itself to append to 
> "samba_log_t" files.

if you have your policy figured out and then go and apply it to 
applications then you are correct.

I'm talking about the situation where you start off by defining a policy 
for Samba, and then afterwords decide that you want to have seperate 
"logfile" and "logdaemon" type then you would need to go back and 
re-examine all the files to tell what needs to be labeled as what.

if you can do all the policy design in advance (and get it right) then 
SELinux is a great solution. if you don't have that time and have to do 
the policy incrementaly you will end up revisiting and revising your 
entire policy each time you go to add something.

> Note that now when "logrotate" runs and rotates files in /var/log/samba, it 
> will automatically create the new files with type "samba_log_t", even though 
> there are no *direct* associations between those types.  If the syslog policy 
> file was poorly written it could seriously adversely affect the security of 
> the system, but hopefully that's obvious :-D.  Policy development is _hard_, 
> it's a whole separate state-machine and pseudo-programming-language that 
> should mostly be left to security professionals or very experienced 
> developers/sysadmins.

I _am_ a security professional. I've been doing security sysadmin work on 
Linux for over a decade now. From your description I'm exactly the type of 
person you are saying should be figuring this out. So please back off of 
the 'this is hard, you should leave it to the professionals' line a 
little bit ;-)

if the AA policies can be compiled into SELinux policies that would work 
(currently they can't and many SELinux people oppose the features that 
would need to be added to make it possible) but the compile process leaves 
room for more bugs in an areas that's going to be hard to investigate. 
(This isn't a fault of SELinux, it's a common issue with compilers, the 
compiled 'thing' is designed to be machine friendly, not user friendly. it 
doesn't matte if it's compiling C into machine code or high-level firewall 
rules into iptables commands or AA policies into SELinux labels and 
policies). adding a complex intermediate layer does not nessasarily add 
security, but it definantly adds complication.

once SELinux has a way for a trusted user to edit a security sensitive 
file (via the process of creating a file and renameing it into place) 
without needing SELinux aware tools and have the result accepted as valid 
by the rest of the system then it becomes possible to implement an AA to 
SELinux policy compiler, but saying that AA should not be accepted becouse 
it's possible to modify SELinux and write such a compile with sufficant 
effort is not reasonable. While there are many cases where multiple ways 
of doing something are not allowed into the kernel (suspend/hibernate is 
an example) there are also cases where multiple ways of doing things are 
allowed, and the LSM hooks are in place explicitly to permit different 
types of security modules to use them.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-06 17:32         ` Greg KH
@ 2007-06-09 23:47           ` Pavel Machek
  0 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-09 23:47 UTC (permalink / raw)
  To: Greg KH
  Cc: Stephen Smalley, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 1847 bytes --]

Hi!

> > > I assume you mean labels instead of handles.
> > > 
> > > AppArmor's design is around paths not labels, and independent of whether or 
> > > not you like AppArmor, this design leads to a useful security model distinct 
> > > from the SELinux security model (which is useful in its own ways). The 
> > > differences between those models cannot be argued away, neither is a subset 
> > > of the other, and neither is a misdesign. I would be thankful if you could 
> > > stop spreading this lie.
> > 
> > I have a hard time distinguishing AppArmor's "model" from its
> > implementation; every time we suggest that one might emulate much of
> > AppArmor's functionality on SELinux (as in SEEdit), someone points to a
> > specific characteristic of the AppArmor implementation that cannot be
> > emulated in this manner.  But is that implementation characteristic an
> > actual requirement or just how it happens to have been done to date in
> > AA?  And I get the impression that even if we extended SELinux in
> > certain ways to ease such emulation, the AA folks would never be
> > satisfied because the implementation would still differ.  Can we
> > separate the desired functionality and actual requirements from the
> > implementation specifics?
> 
> That's a really good point, is there a description of the AA "model"
> anywhere that we could see to determine if there really is a way to
> possibly use the current SELinux internals to show this model to the
> user?

Hmm, techdoc.pdf (attached) is supposed to describe this "model", but
it is more of "AA works like this" with no explanations.... and
includes (probably unwanted) quirks like various races during path
resolution.
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: techdoc.pdf --]
[-- Type: application/pdf, Size: 156018 bytes --]

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  1:06             ` david
  2007-06-09  2:01               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
@ 2007-06-10  8:34               ` Pavel Machek
  2007-06-10  9:04                 ` david
  1 sibling, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-06-10  8:34 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

Hi!

> >So, AA developers, do you have such a document anywhere?  I know there
> >are some old research papers, do they properly describe the current
> >model you are trying to implement here?
> 
> Greg,
>   to implement the AA approach useing SELinux you need to have a way that 
> files that are renamed or created get tagged with the right label 
> automaticaly with no possible race condition.
> 
> If this can be done then it _may_ be possible to do the job that AA is 
> aimed at with SELinux, but the work nessasary to figure out what lables 
> are needed on what file would still make it a non-trivial task.
> 
> as I understand it SELinux puts one label on each file, so if you have 
> three files accessed by two programs such that
> program A accesses files X Y
> program B accesses files Y Z
> 
> then files X Y and Z all need seperate labels with the policy stateing 
> that program A need to access labels X, Y and program B needs to access 
> files Y Z
> 
> extended out this can come close to giving each file it's own label. AA 
> essentially does this and calls the label the path and computes it at 
> runtime instead of storing it somewhere.

Yes, and in the process, AA stores compiled regular expressions in
kernel. Ouch. I'll take "each file it's own label" over _that_ any time. 
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-10  8:34               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Pavel Machek
@ 2007-06-10  9:04                 ` david
  2007-06-10 20:04                   ` Casey Schaufler
  2007-06-10 21:05                   ` Pavel Machek
  0 siblings, 2 replies; 240+ messages in thread
From: david @ 2007-06-10  9:04 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Sun, 10 Jun 2007, Pavel Machek wrote:

> Hi!
>
>>> So, AA developers, do you have such a document anywhere?  I know there
>>> are some old research papers, do they properly describe the current
>>> model you are trying to implement here?
>>
>> Greg,
>>   to implement the AA approach useing SELinux you need to have a way that
>> files that are renamed or created get tagged with the right label
>> automaticaly with no possible race condition.
>>
>> If this can be done then it _may_ be possible to do the job that AA is
>> aimed at with SELinux, but the work nessasary to figure out what lables
>> are needed on what file would still make it a non-trivial task.
>>
>> as I understand it SELinux puts one label on each file, so if you have
>> three files accessed by two programs such that
>> program A accesses files X Y
>> program B accesses files Y Z
>>
>> then files X Y and Z all need seperate labels with the policy stateing
>> that program A need to access labels X, Y and program B needs to access
>> files Y Z
>>
>> extended out this can come close to giving each file it's own label. AA
>> essentially does this and calls the label the path and computes it at
>> runtime instead of storing it somewhere.
>
> Yes, and in the process, AA stores compiled regular expressions in
> kernel. Ouch. I'll take "each file it's own label" over _that_ any time.

and if each file has it's own label you are going to need regex or similar 
to deal with them as well.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  0:17           ` Greg KH
                               ` (2 preceding siblings ...)
  2007-06-09 15:05             ` Andreas Gruenbacher
@ 2007-06-10 17:09             ` Crispin Cowan
  2007-06-15 16:50               ` Greg KH
  3 siblings, 1 reply; 240+ messages in thread
From: Crispin Cowan @ 2007-06-10 17:09 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Greg KH, Stephen Smalley, Pavel Machek, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

Andreas Gruenbacher wrote:
> On Saturday 09 June 2007 02:17, Greg KH wrote:
>   
>> On Sat, Jun 09, 2007 at 12:03:57AM +0200, Andreas Gruenbacher wrote:
>>     
>>> AppArmor is meant to be relatively easy to understand, manage, and
>>>  customize, and introducing a labels layer wouldn't help these goals.
>>>       
>> Woah, that describes the userspace side of AA just fine, it means
>> nothing when it comes to the in-kernel implementation. There is no 
>> reason that you can't implement the same functionality using some
>> totally different in-kernel solution if possible.
>>     
> I agree that the in-kernel implementation could use different abstractions 
> than user-space, provided that the underlying implementation details can be 
> hidden well enough. The key phrase here is "if possible", and in fact "if 
> possible" is much too strong: very many things in software are possible, 
> including user-space drives and a stable kernel module ABI. Some things make 
> sense; others are genuinely bad ideas while still possible.
>   
In particular, to layer AppArmor on top of SELinux, the following
problems must be addressed:

    * New files: when a file is created, it is labeled according to the
      type of the creating process and the type of the parent directory.
      Applications can also use libselinux to use application logic to
      relabel the file, but that is not 'mandatory' policy, and fails in
      cases like cp and mv. AppArmor lets you create a policy that e..g
      says "/home/*/.plan r" to permit fingerd to read everyone's .plan
      file, should it ever exist, and you cannot emulate that with SELinux.
    * Renamed Files: Renaming a file changes the policy with respect to
      that file in AA. To emulate this in SELinux, you would have to
      have a way to instantly re-label the file upon rename.
    * Renamed Directory trees: The above problem is compounded with
      directory trees. Changing the name at the top of a large, bushy
      tree can require instant relabeling of millions of files.
    * New Policies: The SEEdit approach of compiling AA profiles into
      SELinux labels involves computing the partition set of files, so
      that each element of the partition set is unique, and corresponds
      to all the policies that treat every file in the element
      identically. If you create a new profile that touches *some* of
      the files in such an element, then you have to split that
      synthetic label, re-compute the partition set, and re-label the
      file system.
    * File Systems That Do Not Support Labels: The most important being
      NFS3 and FAT. Because they do not support labels at all, SELinux
      has to give you an all-or-nothing access control on the entire
      remote volume. AA can give you nuanced access control in these
      file systems.

You could support all of these features in SELinux, but only by adding
an in-kernel file matching mechanism similar to AppArmor. It would
basically load an AppArmor policy into the kernel, label files as they
are brought from disk into the cache, and then use SELinux to do the
access controls.

That doesn't make it a good idea:

    * The patch would be at least as complex and intrusive as the
      proposed AppArmor patch, there is no simplicity already-upstream
      savings here.
    * It would require the VFS and d_path patches that AppArmor needs to
      pass mount points down.
    * It would make AppArmor's ability to change policies on a live
      system more difficult.
    * The necessary extensions would not be appealing to the SELinux
      community.

LSM is the common code that AA and SELinux have agreed to be mutually
useful. Forcing AA to sit on top of SELinux would harm both AA and SELinux.

Crispin

-- 
Crispin Cowan, Ph.D.               http://crispincowan.com/~crispin/
Director of Software Engineering   http://novell.com
	AppArmor Chat: irc.oftc.net/#apparmor


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-10  9:04                 ` david
@ 2007-06-10 20:04                   ` Casey Schaufler
  2007-06-10 20:51                     ` Crispin Cowan
  2007-06-10 21:05                   ` Pavel Machek
  1 sibling, 1 reply; 240+ messages in thread
From: Casey Schaufler @ 2007-06-10 20:04 UTC (permalink / raw)
  To: david, Pavel Machek
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel


--- david@lang.hm wrote:


> > Yes, and in the process, AA stores compiled regular expressions in
> > kernel. Ouch. I'll take "each file it's own label" over _that_ any time.
> 
> and if each file has it's own label you are going to need regex or similar 
> to deal with them as well.

Now that you're going to have to explain. Nothing like that 
on any of the MLS systems I'm familiar with, and I think that
I know just about all of them.


Casey Schaufler
casey@schaufler-ca.com

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-10 20:04                   ` Casey Schaufler
@ 2007-06-10 20:51                     ` Crispin Cowan
  2007-06-11  6:45                       ` david
  0 siblings, 1 reply; 240+ messages in thread
From: Crispin Cowan @ 2007-06-10 20:51 UTC (permalink / raw)
  To: casey
  Cc: david, Pavel Machek, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

Casey Schaufler wrote:
> --- david@lang.hm wrote:
>   
>>> Yes, and in the process, AA stores compiled regular expressions in
>>> kernel. Ouch. I'll take "each file it's own label" over _that_ any time.
>>>       
>> and if each file has it's own label you are going to need regex or similar 
>> to deal with them as well.
>>     
> Now that you're going to have to explain. Nothing like that 
> on any of the MLS systems I'm familiar with, and I think that
> I know just about all of them.
>   
I suspect that David meant that if you were using "unique label per
file" as an implementation technique to implement AA on top of SELinux,
that you would then need a regexp to discern labels.

It's hard to recall with all the noise, but at this point in the thread
the discussion is about the best way to implement AA. Some have alleged
that AA layered on top of SELinux is the best way. I think that is
clearly wrong; AA layered on top of SELinux is possible, but would
require a bunch of enhancements to SELinux first, and the result would
be more complex than the proposed AA patch and have weaker functionality
and performance.

Crispin

-- 
Crispin Cowan, Ph.D.               http://crispincowan.com/~crispin/
Director of Software Engineering   http://novell.com
	AppArmor Chat: irc.oftc.net/#apparmor


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-09  5:18             ` david
  2007-06-09  5:46               ` Sean
  2007-06-09 16:18               ` Kyle Moffett
@ 2007-06-10 20:54               ` Crispin Cowan
  2007-06-10 21:17                 ` Joshua Brindle
  2 siblings, 1 reply; 240+ messages in thread
From: Crispin Cowan @ 2007-06-10 20:54 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

david@lang.hm wrote:
> On Fri, 8 Jun 2007, Greg KH wrote:
>> I still want to see a definition of the AA "model" that we can then use
>> to try to implement using whatever solution works best.  As that seems
>> to be missing the current argument of if AA can or can not be
>> implemented using SELinux or something totally different should be
>> stopped.
> the way I would describe the difference betwen AA and SELinux is:
>
> SELinux is like a default allow IPS system, you have to describe
> EVERYTHING to the system so that it knows what to allow and what to stop.
>
> AA is like a default deny firewall, you describe what you want to
> happen, and it blocks everything else without you even having to
> realize that it's there.
That's not quite right:

    * SELinux Strict Policy is a default-deny system: it specifies
      everything that is permitted system wide, and all else is denied.
    * AA and the SELinux Targeted Policy are hybrid systems:
          o default-deny within a policy or profile: confined processes
            are only permitted to do what the policy says, and all else
            is denied.
          o default-allow system wide: unconfined processes are allowed
            to do anything that classic DAC permissions allow.

Crispin

-- 
Crispin Cowan, Ph.D.               http://crispincowan.com/~crispin/
Director of Software Engineering   http://novell.com
	AppArmor Chat: irc.oftc.net/#apparmor


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-10  9:04                 ` david
  2007-06-10 20:04                   ` Casey Schaufler
@ 2007-06-10 21:05                   ` Pavel Machek
  2007-06-11  6:27                     ` david
  2007-06-12 17:03                     ` Lars Marowsky-Bree
  1 sibling, 2 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-10 21:05 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

Hi!

> >>extended out this can come close to giving each file it's own label. AA
> >>essentially does this and calls the label the path and computes it at
> >>runtime instead of storing it somewhere.
> >
> >Yes, and in the process, AA stores compiled regular expressions in
> >kernel. Ouch. I'll take "each file it's own label" over _that_ any time.
> 
> and if each file has it's own label you are going to need regex or similar 
> to deal with them as well.

But you have that regex in _user_ space, in a place where policy
is loaded into kernel.

AA has regex parser in _kernel_ space, which is very wrong.
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-10 20:54               ` Crispin Cowan
@ 2007-06-10 21:17                 ` Joshua Brindle
  0 siblings, 0 replies; 240+ messages in thread
From: Joshua Brindle @ 2007-06-10 21:17 UTC (permalink / raw)
  To: Crispin Cowan
  Cc: david, Greg KH, Andreas Gruenbacher, Stephen Smalley,
	Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

Crispin Cowan wrote:
> david@lang.hm wrote:
>   
>> On Fri, 8 Jun 2007, Greg KH wrote:
>>     
>>> I still want to see a definition of the AA "model" that we can then use
>>> to try to implement using whatever solution works best.  As that seems
>>> to be missing the current argument of if AA can or can not be
>>> implemented using SELinux or something totally different should be
>>> stopped.
>>>       
>> the way I would describe the difference betwen AA and SELinux is:
>>
>> SELinux is like a default allow IPS system, you have to describe
>> EVERYTHING to the system so that it knows what to allow and what to stop.
>>
>> AA is like a default deny firewall, you describe what you want to
>> happen, and it blocks everything else without you even having to
>> realize that it's there.
>>     
> That's not quite right:
>
>     * SELinux Strict Policy is a default-deny system: it specifies
>       everything that is permitted system wide, and all else is denied.
>     * AA and the SELinux Targeted Policy are hybrid systems:
>           o default-deny within a policy or profile: confined processes
>             are only permitted to do what the policy says, and all else
>             is denied.
>           o default-allow system wide: unconfined processes are allowed
>             to do anything that classic DAC permissions allow.
>   
Still not completely correct, though the targeted policy has an 
unconfined domain (unconfined_t) the policy still has allow rules for 
everything unconfined can do, 2 examples of things unconfined still 
can't do (because they aren't allowed by the targeted policy) is execmem 
and a while back when there was a /proc exploit that required setattr on 
/proc/self/environ; unconfined_t wasn't able to do that either (and 
therefore the exploit didn't work on a targeted system).

That said, the differentiation between strict and targeted is going away 
soon so that one can have some users be unconfined (but still with a few 
restrictions) and others can be fully restricted.


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-06 13:09                   ` Stephen Smalley
@ 2007-06-10 23:10                     ` Andreas Gruenbacher
  2007-06-11 14:33                       ` Stephen Smalley
  0 siblings, 1 reply; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-10 23:10 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Wednesday 06 June 2007 15:09, Stephen Smalley wrote:
> On Mon, 2007-06-04 at 16:30 +0200, Andreas Gruenbacher wrote:
> > On Monday 04 June 2007 15:12, Pavel Machek wrote:
> > > How will kernel work with very long paths? I'd suspect some problems,
> > > if path is 1MB long and I attempt to print it in /proc
> > > somewhere.
> > 
> > Pathnames are only used for informational purposes in the kernel, except 
> > in AppArmor of course.
> 
> I don't mean this as a flame, but isn't the above statement the very
> crux of this discussion?

I think the question at the core of it all is, shall a pathname based security 
mechanism be allowed. I was under the impression that this question had 
already been answered affirmatively. If the answer here was no, then we could 
stop the entire discussion right there.

> Why should AppArmor be different from the rest of the kernel in its usage of
> pathnames (basis for decisions vs. informational reporting to userspace)? 
> And if it is ok for AppArmor to generate and use pathnames as its basis of
> decisions on each open, then is it also ok for audit, inotify, and others to
> use them in the same manner?

Audit and inotify don't make any decisions based on pathnames, or on SELinux 
labels for that matter, they only report. That being said, sure those parts 
of the kernel that report pathnames should report them correctly -- I guess 
there is no disagreement about that.

> Another question:  it seems like the read-only bind mount folks gave up
> on propagating the vfsmounts down and switched to a rather different
> approach (checking near the entry points, using mount writer counters).
> So similarly, what makes AppArmor fundamentally different that it
> wouldn't take a similar approach to what they are doing vs. propagating
> the vfsmounts down?

Without the vfsmounts propagated down you won't know the pathnames. Whether 
or not a different problem can be solved without the vfsmounts is not really 
relevant.

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-10 21:05                   ` Pavel Machek
@ 2007-06-11  6:27                     ` david
  2007-06-14 19:16                       ` Jack Stone
  2007-06-12 17:03                     ` Lars Marowsky-Bree
  1 sibling, 1 reply; 240+ messages in thread
From: david @ 2007-06-11  6:27 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Sun, 10 Jun 2007, Pavel Machek wrote:

>>>> extended out this can come close to giving each file it's own label. AA
>>>> essentially does this and calls the label the path and computes it at
>>>> runtime instead of storing it somewhere.
>>>
>>> Yes, and in the process, AA stores compiled regular expressions in
>>> kernel. Ouch. I'll take "each file it's own label" over _that_ any time.
>>
>> and if each file has it's own label you are going to need regex or similar
>> to deal with them as well.
>
> But you have that regex in _user_ space, in a place where policy
> is loaded into kernel.

then the kernel is going to have to call out to userspace every time a 
file is created or renamed and the policy is going to be enforced 
incorrectly until userspace finished labeling/relabeling whatever is 
moved. building this sort of race condigion for security into the kernel 
is highly questionable at best.

> AA has regex parser in _kernel_ space, which is very wrong.

see Linus' rants about why it's not automaticaly the best thing to move 
functionality into userspace.

remember that the files covered by an AA policy can change as files are 
renamed. this isn't the case with SELinux so it doesn't have this sort of 
problem.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-10 20:51                     ` Crispin Cowan
@ 2007-06-11  6:45                       ` david
  2007-06-11  8:29                         ` Sean
  2007-06-11 11:00                         ` Pavel Machek
  0 siblings, 2 replies; 240+ messages in thread
From: david @ 2007-06-11  6:45 UTC (permalink / raw)
  To: Crispin Cowan
  Cc: casey, Pavel Machek, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Sun, 10 Jun 2007, Crispin Cowan wrote:

> Casey Schaufler wrote:
>> --- david@lang.hm wrote:
>>
>>>> Yes, and in the process, AA stores compiled regular expressions in
>>>> kernel. Ouch. I'll take "each file it's own label" over _that_ any time.
>>>>
>>> and if each file has it's own label you are going to need regex or similar
>>> to deal with them as well.
>>>
>> Now that you're going to have to explain. Nothing like that
>> on any of the MLS systems I'm familiar with, and I think that
>> I know just about all of them.
>>
> I suspect that David meant that if you were using "unique label per
> file" as an implementation technique to implement AA on top of SELinux,
> that you would then need a regexp to discern labels.

exactly.

say that we give each file a unique label, and for simplicity we set the 
label == path (note that this raises the issue, what will SELinux do when 
there are multiple paths to the same file)

now say that you want to grant apache access to all files that have labels 
that follow the pattern '/home/*/http/* ?

you are either going to use regex matching, or you are going to have to 
enumerate every label that matches this (potentially a very large list). 
and if you try to generate the enumerated list you need to add a label to 
the list if a file is renamed or created to match the pattern, and delete 
a file from the list if it is renamed to no longer match the pattern

> It's hard to recall with all the noise, but at this point in the thread
> the discussion is about the best way to implement AA. Some have alleged
> that AA layered on top of SELinux is the best way. I think that is
> clearly wrong; AA layered on top of SELinux is possible, but would
> require a bunch of enhancements to SELinux first, and the result would
> be more complex than the proposed AA patch and have weaker functionality
> and performance.

AA as-is needs to figure out how to deal with bind-mounts, and how to 
handle hardlink creation in a more ganular manner (and potentially other 
resources like network sockets), but it's useful now even without these 
improvements


AA over SELinux would need for SELinux to figure out how to handle file 
creation, file renames, and multiple paths for the same file (hard-links 
and bind-mounts). In addition a userspace daemon would have to be written 
to re-label files and/or change policy on the fly as files are renamed. 
the result would still have race conditions due to the need to re-label 
large numbers of files


ACPI should have taught everyone that sometimes putting an interpreter in 
the kernel really is the best option. looking at the problems of bouncing 
back out to userspace for file creation and renames it looks like a regex 
in the kernel is a lot safer and more reliable.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-11  6:45                       ` david
@ 2007-06-11  8:29                         ` Sean
  2007-06-11  9:33                           ` david
  2007-06-11 11:00                         ` Pavel Machek
  1 sibling, 1 reply; 240+ messages in thread
From: Sean @ 2007-06-11  8:29 UTC (permalink / raw)
  To: david
  Cc: Crispin Cowan, casey, Pavel Machek, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Sun, 10 Jun 2007 23:45:16 -0700 (PDT)
david@lang.hm wrote:

> say that we give each file a unique label, and for simplicity we set the 
> label == path (note that this raises the issue, what will SELinux do when 
> there are multiple paths to the same file)

So don't do that then.

> now say that you want to grant apache access to all files that have labels 
> that follow the pattern '/home/*/http/* ?
> 
> you are either going to use regex matching, or you are going to have to 
> enumerate every label that matches this (potentially a very large list). 
> and if you try to generate the enumerated list you need to add a label to 
> the list if a file is renamed or created to match the pattern, and delete 
> a file from the list if it is renamed to no longer match the pattern

If AA requires regex matching in the kernel, perhaps it really isn't
appropriate for inclusion.  Surely there has to be a better way than
requiring the kernel to do regex matches at runtime?

> AA over SELinux would need for SELinux to figure out how to handle file 
> creation, file renames, and multiple paths for the same file (hard-links 
> and bind-mounts). In addition a userspace daemon would have to be written 
> to re-label files and/or change policy on the fly as files are renamed. 
> the result would still have race conditions due to the need to re-label 
> large numbers of files

WRONG.  The labels would be obtained from AA as needed, never recorded in
the file attributes.  This would change nothing about what AA needed
to compute at runtime, just the way it implements the result.

> ACPI should have taught everyone that sometimes putting an interpreter in 
> the kernel really is the best option. looking at the problems of bouncing 
> back out to userspace for file creation and renames it looks like a regex 
> in the kernel is a lot safer and more reliable.

There hasn't yet been shown a requirement for a userspace daemon to implement
AA over SeLinux.

Sean

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-11  8:29                         ` Sean
@ 2007-06-11  9:33                           ` david
  2007-06-11 11:34                             ` Sean
  0 siblings, 1 reply; 240+ messages in thread
From: david @ 2007-06-11  9:33 UTC (permalink / raw)
  To: Sean
  Cc: Crispin Cowan, casey, Pavel Machek, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Mon, 11 Jun 2007, Sean wrote:

> david@lang.hm wrote:
>
>> say that we give each file a unique label, and for simplicity we set the
>> label == path (note that this raises the issue, what will SELinux do when
>> there are multiple paths to the same file)
>
> So don't do that then.
>
>> now say that you want to grant apache access to all files that have labels
>> that follow the pattern '/home/*/http/* ?
>>
>> you are either going to use regex matching, or you are going to have to
>> enumerate every label that matches this (potentially a very large list).
>> and if you try to generate the enumerated list you need to add a label to
>> the list if a file is renamed or created to match the pattern, and delete
>> a file from the list if it is renamed to no longer match the pattern
>
> If AA requires regex matching in the kernel, perhaps it really isn't
> appropriate for inclusion.  Surely there has to be a better way than
> requiring the kernel to do regex matches at runtime?
>
>> AA over SELinux would need for SELinux to figure out how to handle file
>> creation, file renames, and multiple paths for the same file (hard-links
>> and bind-mounts). In addition a userspace daemon would have to be written
>> to re-label files and/or change policy on the fly as files are renamed.
>> the result would still have race conditions due to the need to re-label
>> large numbers of files
>
> WRONG.  The labels would be obtained from AA as needed, never recorded in
> the file attributes.  This would change nothing about what AA needed
> to compute at runtime, just the way it implements the result.

Ok, you are proposing throwing out all the label handling that SELinux 
does, including any caching. forgive me if I agree with the SELinux people 
that this is a very bad idea.

>> ACPI should have taught everyone that sometimes putting an interpreter in
>> the kernel really is the best option. looking at the problems of bouncing
>> back out to userspace for file creation and renames it looks like a regex
>> in the kernel is a lot safer and more reliable.
>
> There hasn't yet been shown a requirement for a userspace daemon to implement
> AA over SeLinux.

I thought the userspace component was what you were proposing instead of 
doing the regex matching in the kernel. if this isn't it what exactly are 
you proposing?

you don't want the regex matching in the kernel.

you don't want a userspace component to do the regex matching when files 
are created or renamed.

how exactly do you propose to figure out what should happen to a file when 
it is created or it (or a parent directory) is renamed?

AA policies are defined in terms of regex expressions. you say that this 
should be able to be done on top of SELinux somehow without changing the 
policies. so somewhere, something needs to interpret the regex to see if 
it matches the path. this needs to be either kernel code or userspace 
code. you have ruled out kernel code and are now claiming that userspace 
isn't needed.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-11  6:45                       ` david
  2007-06-11  8:29                         ` Sean
@ 2007-06-11 11:00                         ` Pavel Machek
  1 sibling, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-11 11:00 UTC (permalink / raw)
  To: david
  Cc: Crispin Cowan, casey, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

Hi!

> ACPI should have taught everyone that sometimes putting an interpreter in 
> the kernel really is the best option. looking at the problems of bouncing 
> back out to userspace for file creation and renames it looks like a regex 
> in the kernel is a lot safer and more reliable.

What do ACPI and AA have in common?

* they both start with A

* there are both nightmare

* they both put interpretter into kernel

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-11  9:33                           ` david
@ 2007-06-11 11:34                             ` Sean
  0 siblings, 0 replies; 240+ messages in thread
From: Sean @ 2007-06-11 11:34 UTC (permalink / raw)
  To: david
  Cc: Crispin Cowan, casey, Pavel Machek, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Mon, 11 Jun 2007 02:33:30 -0700 (PDT)
david@lang.hm wrote:

> Ok, you are proposing throwing out all the label handling that SELinux 
> does, including any caching. forgive me if I agree with the SELinux people 
> that this is a very bad idea.

Well presumably AA would be doing caching etc.. so that doesn't seem like
a problem.  The SELinux people seem to think that accepting AA into the
kernel and supporting path based security at all is a mistake.  I guess
I forgive you for agreeing with them ;)

> I thought the userspace component was what you were proposing instead of 
> doing the regex matching in the kernel. if this isn't it what exactly are 
> you proposing?

No.. i've said quite a few times now that i'm not talking about calling out
to userspace.  The entire discussion of regex matching is a completely
separate discussion.  It's either the right thing to do, or not.  But the
same issues in regard to regex matching apply whether AA is built on top
of SELinux or not.

> AA policies are defined in terms of regex expressions. you say that this 
> should be able to be done on top of SELinux somehow without changing the 
> policies. so somewhere, something needs to interpret the regex to see if 
> it matches the path. this needs to be either kernel code or userspace 
> code. you have ruled out kernel code and are now claiming that userspace 
> isn't needed.

For whatever it's worth, i'll repeat again.   The AA kernel extension would
be associating paths with labels (using regex, or not).  At that point all
policy decisions would be enforced by SELinux using standard SELinux policy
rules.   The SELinux policy would be a translated version of the AA policy
file.  The translation could of course happen in userland.

The net affect of all that... is that you get a version of SELinux which
can be configured with the user friendly AA policy file format.   And,
files won't need to carry around security labels with them.  I leave
the debate about whether that's a good idea in general to others.  But
from what i can tell, it's the only significant difference between
SELinux and AA.

Depending on the way it was implemented, its conceivable that users could
mix and match native SELinux policy with custom AA policies as they
saw fit.

Sean

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-10 23:10                     ` Andreas Gruenbacher
@ 2007-06-11 14:33                       ` Stephen Smalley
  2007-06-11 15:55                         ` Andreas Gruenbacher
  2007-06-12 23:50                         ` Andreas Gruenbacher
  0 siblings, 2 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-11 14:33 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Mon, 2007-06-11 at 01:10 +0200, Andreas Gruenbacher wrote:
> On Wednesday 06 June 2007 15:09, Stephen Smalley wrote:
> > On Mon, 2007-06-04 at 16:30 +0200, Andreas Gruenbacher wrote:
> > > On Monday 04 June 2007 15:12, Pavel Machek wrote:
> > > > How will kernel work with very long paths? I'd suspect some problems,
> > > > if path is 1MB long and I attempt to print it in /proc
> > > > somewhere.
> > > 
> > > Pathnames are only used for informational purposes in the kernel, except 
> > > in AppArmor of course.
> > 
> > I don't mean this as a flame, but isn't the above statement the very
> > crux of this discussion?
> 
> I think the question at the core of it all is, shall a pathname based security 
> mechanism be allowed. I was under the impression that this question had 
> already been answered affirmatively. If the answer here was no, then we could 
> stop the entire discussion right there.

There is a difference between using the pathname at the kernel/userland
interface as part of configuring a security mechanism and using it as
the basis for the runtime checking itself.  Further, there is a
difference between generating and matching full pathnames on each access
vs. caching information in the parent dentry and making decisions based
on that cached information and the last component-name.  The only
question I saw being answered was the abstract one of "can a pathname
play a role in the security mechanism" not "should the kernel be
regenerating a full path on each open and glob matching it against a
list of file globs."

> > Why should AppArmor be different from the rest of the kernel in its usage of
> > pathnames (basis for decisions vs. informational reporting to userspace)? 
> > And if it is ok for AppArmor to generate and use pathnames as its basis of
> > decisions on each open, then is it also ok for audit, inotify, and others to
> > use them in the same manner?
> 
> Audit and inotify don't make any decisions based on pathnames, or on SELinux 
> labels for that matter, they only report. That being said, sure those parts 
> of the kernel that report pathnames should report them correctly -- I guess 
> there is no disagreement about that.

>From a userland perspective, audit and inotify allow you to specify
watches on pathnames, and those watches trigger actions by the audit and
inotify subsystems when those files are accessed.  The kernel mechanism
however is inode-based, not pathname-based; the pathname is merely
looked up when the watch is added and mapped to an inode.  That's my
point - why should AA be different?  Would you really recommend that
audit or inotify call d_path() on each open and glob match the result
against a list of audit or inotify watches?  BTW, audit does allow
filters on SELinux labels these days.

> > Another question:  it seems like the read-only bind mount folks gave up
> > on propagating the vfsmounts down and switched to a rather different
> > approach (checking near the entry points, using mount writer counters).
> > So similarly, what makes AppArmor fundamentally different that it
> > wouldn't take a similar approach to what they are doing vs. propagating
> > the vfsmounts down?
> 
> Without the vfsmounts propagated down you won't know the pathnames. Whether 
> or not a different problem can be solved without the vfsmounts is not really 
> relevant.

Well, that presumes that your mechanism has to generate full pathnames
on each access check.  But even if so, you could be doing your checking
in the higher level code then where you have a vfsmount available.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-08 22:03         ` Andreas Gruenbacher
  2007-06-09  0:17           ` Greg KH
@ 2007-06-11 15:16           ` Stephen Smalley
  1 sibling, 0 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-11 15:16 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel, Karl MacMillan

On Sat, 2007-06-09 at 00:03 +0200, Andreas Gruenbacher wrote:
> On Wednesday 06 June 2007 15:26, Stephen Smalley wrote:
> > - under AA, each file may have an arbitrary set of "labels" or
> > "policies" applied to it depending on what programs are accessing it and
> > what names are being used to reference it - there is no system view of
> > the subjects and objects and thus no way to identify the overall system
> > policy for a given file.
> 
> Look at it this way: under SELinux, the set of files that share a label forms 
> an equivalence class -- they are all treated identically by the system's 
> security policy. The rules in AppArmor profiles also define equivalence 
> classes in the sense that they partition the filesystem namespace into sets 
> of files that are treated identically, but this classification is not 
> explicit -- the entire rule base contributes to the classification. This 
> doesn't mean that there is not a global policy, just that the policy is 
> modeled differently. The equivalence classes are not directly obvious from 
> the AA profiles.

No, it really does mean that there is no global policy, and it goes
beyond "not directly obvious" to "can not be determined" from the AA
profiles.  You can't compose the set of AA profiles and say anything
useful, because they are written in terms of ambiguous and unstable
identifiers.  /a/b/c may refer to completely different objects in two
different profiles, or to the same object as /d/e/f in the same or
another profile.

> Contrast this with SEEdit, which compiles AA-style rules into labels (and thus 
> equivalence classes). The resulting SELinux policy is a static snapshot that 
> cannot easily accommodate rule base changes, is more limited with respect to 
> new files (which would likely be fixable), and behaves differently in complex 
> ways with file renames. What's more, most likely the compiled policy will be 
> anywhere from very hard to impossible to analyze, so you pretty much lose on 
> all ends.

Just to clarify, you can change the allowed accesses from a given
subject to a given object without relabeling, just by changing the
policy allow rules; you only have to relabel the object in the case
where you want to distinguish that object from another object with the
same label for the same subject.  I think the new file situation could
be improved without any major change to the SELinux model, and am not
opposed to leveraging the component name there, as previously noted.  On
the file rename case, I think we have it right - access rights shouldn't
change automatically when a file is renamed, any more than DAC ownership
or file modes should.

> > - names are far less tranquil than labels.
> 
> If I'm getting things right, a tranquil system with respect to labels would be 
> one that does not permit re-labeling, while a tranquil system with respect to 
> path names would be one that does not permit renaming. Both approaches would 
> buy greater analyzability with reduced usability, and both seem unrealistic 
> to me. SELinux and AppArmor evidently have different goals, and tranquility 
> is more important to SELinux.

Tranquility is important to correctness and understandability of policy;
if labels (or pathnames in your case) can change at any time, then you
have the problems of revocation of access (impractical to completely
implement in Linux) and your effective policy now varies over time, so
you have to consider time as a factor in your policy analysis.

> AppArmor is meant to be relatively easy to understand, manage, and customize, 
> and introducing a labels layer wouldn't help these goals. SELinux is 
> applicable in areas where AppArmor is not (e.g., MLS), but this comes at a 
> cost. For me the question is not SELinux or AppArmor, but if AppArmor's 
> security model is a good solution in common scenarios. In my opinion, 
> AppArmor is a better answer than SELinux in a number of scenarios. This gives 
> it value, nonwithstanding the fact that SELinux can be taken further.

I'd agree that we shouldn't try to emulate AA as it is on SELinux.  The
question is more of whether we can meet the higher level functionality
goals that make some people want to use AA via SELinux.  That requires
separating those goals from the implementation details of AA.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-11 14:33                       ` Stephen Smalley
@ 2007-06-11 15:55                         ` Andreas Gruenbacher
  2007-06-11 19:02                           ` Serge E. Hallyn
  2007-06-12 13:13                           ` Stephen Smalley
  2007-06-12 23:50                         ` Andreas Gruenbacher
  1 sibling, 2 replies; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-11 15:55 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Monday 11 June 2007 16:33, Stephen Smalley wrote:
> On Mon, 2007-06-11 at 01:10 +0200, Andreas Gruenbacher wrote:
> > On Wednesday 06 June 2007 15:09, Stephen Smalley wrote:
> > > On Mon, 2007-06-04 at 16:30 +0200, Andreas Gruenbacher wrote:
> > > > On Monday 04 June 2007 15:12, Pavel Machek wrote:
> > > > > How will kernel work with very long paths? I'd suspect some
> > > > > problems, if path is 1MB long and I attempt to print it in /proc
> > > > > somewhere.
> > > >
> > > > Pathnames are only used for informational purposes in the kernel,
> > > > except in AppArmor of course.
> > >
> > > I don't mean this as a flame, but isn't the above statement the very
> > > crux of this discussion?
> >
> > I think the question at the core of it all is, shall a pathname based
> > security mechanism be allowed. I was under the impression that this
> > question had already been answered affirmatively. If the answer here was
> > no, then we could stop the entire discussion right there.
>
> There is a difference between using the pathname at the kernel/userland
> interface as part of configuring a security mechanism and using it as
> the basis for the runtime checking itself.

Yes, there is a difference. When I say pathname based security mechanism, I 
literally mean a pathname based security mechanism, meaning the pathnames 
determine the outcome o the decision. This includes designs that are based on 
different abstractions internally, but the bahavior observable from 
user-space must be the same (or else, it's a different model).

Unfortunately, translating pathnames to labels destroys this fundamental 
abstraction. We explained why this is so in the following postings:

	http://lkml.org/lkml/2007/6/9/94
	http://lkml.org/lkml/2007/6/10/141

> Further, there is a difference between generating and matching full
> pathnames on each access vs. caching information in the parent dentry and
> making decisions based on that cached information and the last
> component-name.

Wait, you are mixing two issues here: access checks on existing files, and the 
creation of new files. For AppArmor as it stands today the two are the same, 
but when looking at emulating AppArmor using labels, they are not. Let's look 
at things one at a time.

Generating and matching full pathnames on each access takes time, no question 
about that. (In fact we are not checking on each access but only when 
pathnames are involved, such as on open. Filehandle based operations do not 
require access checks, but that's not a very important difference at this 
level of discussion.) That's a quantitative statement though, not a 
qualitative one: retrieving xattrs and checking labels also takes time; 
additional checks are never for free. We find that doing the pathname checks 
is easily fast enough. You may disagree, but then you don't have to use 
AppArmor, and we are not standing in your way.

As far as new files are concerned, basing decisions on the parent dentry and 
component name requires that you know where in the filesystem hierarchy this 
dentry is located: with bind mounts, the same dentry shows up in multiple 
locations in a process's namespace, corresponding to different pathnames. In 
other words, to make the right decision, the dentry alone is not enough; it 
takes a <dentry, vfsmount> pair. So there we are again.

>From the point on where you have a <dentry, vfsmount> pair of objects, you can 
do two things: you can compute the full pathname and base your decision on 
that, or you can do some caching to hopefully cut some of that work short 
frequently enough to set off the additional cost. The difference between the 
two approaches is quantitative -- if there is a difference in results, then 
that's obviously a bug. I believe that caching could speed up things 
measurably, but up to this point, neither I nor anybody else had the time to 
look into it, and so we are not doing it -- not yet, any perhaps never at 
all. It may be counter to your intuition, but doing those checks is not a big 
issue.

> The only question I saw being answered was the abstract one of "can a
> pathname play a role in the security mechanism" not "should the kernel be
> regenerating a full path on each open and glob matching it against a
> list of file globs."

No glob matching involved, and no list of patterns. There is a single DFA per 
profile (and each process is in at most one profile at any one time), and 
each access check involves exactly one DFA traversal.

[cut here for lack of time right now -- will take another look later]

> > Without the vfsmounts propagated down you won't know the pathnames.
> > Whether or not a different problem can be solved without the vfsmounts is
> > not really relevant.
>
> Well, that presumes that your mechanism has to generate full pathnames
> on each access check.  But even if so, you could be doing your checking
> in the higher level code then where you have a vfsmount available.

The LSM hooks are pretty high-level, meant for being able to plug in different 
access checks. That's the right level of abstraction. We just need the 
vfsmounts passed down as well. That's what the bulk of common code patches 
are there for.

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-11 15:55                         ` Andreas Gruenbacher
@ 2007-06-11 19:02                           ` Serge E. Hallyn
  2007-06-12 13:00                             ` Stephen Smalley
  2007-06-12 13:13                           ` Stephen Smalley
  1 sibling, 1 reply; 240+ messages in thread
From: Serge E. Hallyn @ 2007-06-11 19:02 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Stephen Smalley, Pavel Machek, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

Quoting Andreas Gruenbacher (agruen@suse.de):
> On Monday 11 June 2007 16:33, Stephen Smalley wrote:
> > On Mon, 2007-06-11 at 01:10 +0200, Andreas Gruenbacher wrote:
> > > On Wednesday 06 June 2007 15:09, Stephen Smalley wrote:
> > > > On Mon, 2007-06-04 at 16:30 +0200, Andreas Gruenbacher wrote:
> > > > > On Monday 04 June 2007 15:12, Pavel Machek wrote:
> > > > > > How will kernel work with very long paths? I'd suspect some
> > > > > > problems, if path is 1MB long and I attempt to print it in /proc
> > > > > > somewhere.
> > > > >
> > > > > Pathnames are only used for informational purposes in the kernel,
> > > > > except in AppArmor of course.
> > > >
> > > > I don't mean this as a flame, but isn't the above statement the very
> > > > crux of this discussion?
> > >
> > > I think the question at the core of it all is, shall a pathname based
> > > security mechanism be allowed. I was under the impression that this
> > > question had already been answered affirmatively. If the answer here was

That was the decision at ksummit last year, yes.

> > > no, then we could stop the entire discussion right there.
> >
> > There is a difference between using the pathname at the kernel/userland
> > interface as part of configuring a security mechanism and using it as
> > the basis for the runtime checking itself.
> 
> Yes, there is a difference. When I say pathname based security mechanism, I 
> literally mean a pathname based security mechanism, meaning the pathnames 
> determine the outcome o the decision. This includes designs that are based on 
> different abstractions internally, but the bahavior observable from 
> user-space must be the same (or else, it's a different model).
> 
> Unfortunately, translating pathnames to labels destroys this fundamental 
> abstraction. We explained why this is so in the following postings:
> 
> 	http://lkml.org/lkml/2007/6/9/94
> 	http://lkml.org/lkml/2007/6/10/141
> 
> > Further, there is a difference between generating and matching full
> > pathnames on each access vs. caching information in the parent dentry and
> > making decisions based on that cached information and the last
> > component-name.
> 
> Wait, you are mixing two issues here: access checks on existing files, and the 
> creation of new files. For AppArmor as it stands today the two are the same, 
> but when looking at emulating AppArmor using labels, they are not. Let's look 
> at things one at a time.
> 
> Generating and matching full pathnames on each access takes time, no question 
> about that. (In fact we are not checking on each access but only when 
> pathnames are involved, such as on open. Filehandle based operations do not 
> require access checks, but that's not a very important difference at this 
> level of discussion.) That's a quantitative statement though, not a 
> qualitative one: retrieving xattrs and checking labels also takes time; 
> additional checks are never for free. We find that doing the pathname checks 
> is easily fast enough. You may disagree, but then you don't have to use 
> AppArmor, and we are not standing in your way.
> 
> As far as new files are concerned, basing decisions on the parent dentry and 
> component name requires that you know where in the filesystem hierarchy this 
> dentry is located: with bind mounts, the same dentry shows up in multiple 
> locations in a process's namespace, corresponding to different pathnames. In 
> other words, to make the right decision, the dentry alone is not enough; it 
> takes a <dentry, vfsmount> pair. So there we are again.
> 
> >From the point on where you have a <dentry, vfsmount> pair of objects, you can 
> do two things: you can compute the full pathname and base your decision on 
> that, or you can do some caching to hopefully cut some of that work short 
> frequently enough to set off the additional cost. The difference between the 
> two approaches is quantitative -- if there is a difference in results, then 
> that's obviously a bug. I believe that caching could speed up things 
> measurably, but up to this point, neither I nor anybody else had the time to 
> look into it, and so we are not doing it -- not yet, any perhaps never at 
> all. It may be counter to your intuition, but doing those checks is not a big 
> issue.

My approach in DTE, which used pathnames to assign TE labels in the
kernel, was to use a 'shadow tree' to the vfsmnt+dentry tree, filled out
at policy load time to the depth of the deepest policy rule.  For the
behavior I was after, bind mounts were handled by storing pointers from
the new mount to the original, but the behavior AA wants would be
different.  Namespace clones are easily handled this way by copying the
cached pointers to the shadow tree.  And it was pretty fast.

When I talked about this with Tony last year, the biggest shortcoming to
use this for AA was the wildcards.  For instance, if there is a rule for
/var/log/HOSTS/*/messages, then when /var/log/HOSTS/sergelap/ is
created, a new rule would have to be created on the fly to tag
/var/log/HOSTS/sergelap/messages if it is created.  How to represent
that when only /var/log or /var/log/HOSTS exists at policy load time
would be, well, a fun problem to solve actually  :)

-serge

> > The only question I saw being answered was the abstract one of "can a
> > pathname play a role in the security mechanism" not "should the kernel be
> > regenerating a full path on each open and glob matching it against a
> > list of file globs."
> 
> No glob matching involved, and no list of patterns. There is a single DFA per 
> profile (and each process is in at most one profile at any one time), and 
> each access check involves exactly one DFA traversal.
> 
> [cut here for lack of time right now -- will take another look later]
> 
> > > Without the vfsmounts propagated down you won't know the pathnames.
> > > Whether or not a different problem can be solved without the vfsmounts is
> > > not really relevant.
> >
> > Well, that presumes that your mechanism has to generate full pathnames
> > on each access check.  But even if so, you could be doing your checking
> > in the higher level code then where you have a vfsmount available.
> 
> The LSM hooks are pretty high-level, meant for being able to plug in different 
> access checks. That's the right level of abstraction. We just need the 
> vfsmounts passed down as well. That's what the bulk of common code patches 
> are there for.
> 
> Andreas
> -
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-12 15:34                               ` Serge E. Hallyn
@ 2007-06-12  5:17                                 ` Karl MacMillan
  2007-06-12 19:00                                   ` Serge E. Hallyn
  0 siblings, 1 reply; 240+ messages in thread
From: Karl MacMillan @ 2007-06-12  5:17 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: Stephen Smalley, Andreas Gruenbacher, Pavel Machek, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Tue, 2007-06-12 at 10:34 -0500, Serge E. Hallyn wrote:
> Quoting Stephen Smalley (sds@tycho.nsa.gov):

[...]

> > 
> > If we added support for named type transitions to SELinux, as proposed
> > earlier by Kyle Moffett during this discussion, wouldn't that address
> > that issue without needing a DTE-like approach?  The concept is to add
> 
> Haven't read his message, but based on what you laid out here sure, that
> sounds good.  It still, like my dte approach, might have some trouble
> with the wildcard/regex rules AA allows.  And while it might perfectly
> reproduce my original DTE behavior, I don't think it does what AA wants
> on bind mounts.  (Whether what AA wants for bind mounts makes sense I'm
> still not convinced, especially with user mounts coming soon (or already
> here?), but I'm staying out of that discussion for now)
> 
> > the last component name as a further input to the labeling decision for
> > new files, in addition to the existing use of the creating process'
> > label, the parent directory label, and the kind of file.  Then, you
> > could have something like:
> > type_transition <domain> var_log_hosts_t:file "messages" messages_t;
> > 
> > The last component name is already available, so that doesn't require
> > any changes to LSM, and it would be a straightforward extension of
> > SELinux to support the above - it doesn't change the model at all, just
> > adds a further input to the new file labeling logic.
> 
> And eliminates the need for restorecond?
> 

Unlikely in the short term - restorecond is also used to reset contexts
on critical files in /etc that might loose the context because tools
used to update them are not correctly preserving contexts
(e.g., /etc/mtab, etc/resolv.conf).

Actually - this whole notion restorecond as a critical component of
SELinux because of a "new file problem" is pretty overblown. The default
config file ships with:

/etc/resolv.conf
/etc/samba/secrets.tdb
/etc/mtab
/var/run/utmp
/var/log/wtmp
~/public_html
~/.mozilla/plugins/libflashplayer.so

So the only things that would be helped by type_transition rules with a 
name component would be public_html and libflashplayer.so.

Karl


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-11 19:02                           ` Serge E. Hallyn
@ 2007-06-12 13:00                             ` Stephen Smalley
  2007-06-12 15:34                               ` Serge E. Hallyn
  0 siblings, 1 reply; 240+ messages in thread
From: Stephen Smalley @ 2007-06-12 13:00 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: Andreas Gruenbacher, Pavel Machek, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Mon, 2007-06-11 at 14:02 -0500, Serge E. Hallyn wrote:
> Quoting Andreas Gruenbacher (agruen@suse.de):
> > On Monday 11 June 2007 16:33, Stephen Smalley wrote:
> > > On Mon, 2007-06-11 at 01:10 +0200, Andreas Gruenbacher wrote:
> > > > On Wednesday 06 June 2007 15:09, Stephen Smalley wrote:
> > > > > On Mon, 2007-06-04 at 16:30 +0200, Andreas Gruenbacher wrote:
> > > > > > On Monday 04 June 2007 15:12, Pavel Machek wrote:
> > > > > > > How will kernel work with very long paths? I'd suspect some
> > > > > > > problems, if path is 1MB long and I attempt to print it in /proc
> > > > > > > somewhere.
> > > > > >
> > > > > > Pathnames are only used for informational purposes in the kernel,
> > > > > > except in AppArmor of course.
> > > > >
> > > > > I don't mean this as a flame, but isn't the above statement the very
> > > > > crux of this discussion?
> > > >
> > > > I think the question at the core of it all is, shall a pathname based
> > > > security mechanism be allowed. I was under the impression that this
> > > > question had already been answered affirmatively. If the answer here was
> 
> That was the decision at ksummit last year, yes.
> 
> > > > no, then we could stop the entire discussion right there.
> > >
> > > There is a difference between using the pathname at the kernel/userland
> > > interface as part of configuring a security mechanism and using it as
> > > the basis for the runtime checking itself.
> > 
> > Yes, there is a difference. When I say pathname based security mechanism, I 
> > literally mean a pathname based security mechanism, meaning the pathnames 
> > determine the outcome o the decision. This includes designs that are based on 
> > different abstractions internally, but the bahavior observable from 
> > user-space must be the same (or else, it's a different model).
> > 
> > Unfortunately, translating pathnames to labels destroys this fundamental 
> > abstraction. We explained why this is so in the following postings:
> > 
> > 	http://lkml.org/lkml/2007/6/9/94
> > 	http://lkml.org/lkml/2007/6/10/141
> > 
> > > Further, there is a difference between generating and matching full
> > > pathnames on each access vs. caching information in the parent dentry and
> > > making decisions based on that cached information and the last
> > > component-name.
> > 
> > Wait, you are mixing two issues here: access checks on existing files, and the 
> > creation of new files. For AppArmor as it stands today the two are the same, 
> > but when looking at emulating AppArmor using labels, they are not. Let's look 
> > at things one at a time.
> > 
> > Generating and matching full pathnames on each access takes time, no question 
> > about that. (In fact we are not checking on each access but only when 
> > pathnames are involved, such as on open. Filehandle based operations do not 
> > require access checks, but that's not a very important difference at this 
> > level of discussion.) That's a quantitative statement though, not a 
> > qualitative one: retrieving xattrs and checking labels also takes time; 
> > additional checks are never for free. We find that doing the pathname checks 
> > is easily fast enough. You may disagree, but then you don't have to use 
> > AppArmor, and we are not standing in your way.
> > 
> > As far as new files are concerned, basing decisions on the parent dentry and 
> > component name requires that you know where in the filesystem hierarchy this 
> > dentry is located: with bind mounts, the same dentry shows up in multiple 
> > locations in a process's namespace, corresponding to different pathnames. In 
> > other words, to make the right decision, the dentry alone is not enough; it 
> > takes a <dentry, vfsmount> pair. So there we are again.
> > 
> > >From the point on where you have a <dentry, vfsmount> pair of objects, you can 
> > do two things: you can compute the full pathname and base your decision on 
> > that, or you can do some caching to hopefully cut some of that work short 
> > frequently enough to set off the additional cost. The difference between the 
> > two approaches is quantitative -- if there is a difference in results, then 
> > that's obviously a bug. I believe that caching could speed up things 
> > measurably, but up to this point, neither I nor anybody else had the time to 
> > look into it, and so we are not doing it -- not yet, any perhaps never at 
> > all. It may be counter to your intuition, but doing those checks is not a big 
> > issue.
> 
> My approach in DTE, which used pathnames to assign TE labels in the
> kernel, was to use a 'shadow tree' to the vfsmnt+dentry tree, filled out
> at policy load time to the depth of the deepest policy rule.  For the
> behavior I was after, bind mounts were handled by storing pointers from
> the new mount to the original, but the behavior AA wants would be
> different.  Namespace clones are easily handled this way by copying the
> cached pointers to the shadow tree.  And it was pretty fast.
> 
> When I talked about this with Tony last year, the biggest shortcoming to
> use this for AA was the wildcards.  For instance, if there is a rule for
> /var/log/HOSTS/*/messages, then when /var/log/HOSTS/sergelap/ is
> created, a new rule would have to be created on the fly to tag
> /var/log/HOSTS/sergelap/messages if it is created.  How to represent
> that when only /var/log or /var/log/HOSTS exists at policy load time
> would be, well, a fun problem to solve actually  :)

If we added support for named type transitions to SELinux, as proposed
earlier by Kyle Moffett during this discussion, wouldn't that address
that issue without needing a DTE-like approach?  The concept is to add
the last component name as a further input to the labeling decision for
new files, in addition to the existing use of the creating process'
label, the parent directory label, and the kind of file.  Then, you
could have something like:
type_transition <domain> var_log_hosts_t:file "messages" messages_t;

The last component name is already available, so that doesn't require
any changes to LSM, and it would be a straightforward extension of
SELinux to support the above - it doesn't change the model at all, just
adds a further input to the new file labeling logic.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-09 13:44                     ` Andreas Gruenbacher
@ 2007-06-12 13:06                       ` Pavel Machek
  0 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-12 13:06 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: jjohansen, linux-kernel, linux-security-module, linux-fsdevel

Hi!

> > > > How will kernel work with very long paths? I'd suspect some problems,
> > > > if path is 1MB long and I attempt to print it in /proc
> > > > somewhere.
> > > 
> > > Pathnames are only used for informational purposes in the kernel, except 
> > > in AppArmor of course. /proc only uses pathnames in a few places, 
> > > but /proc/mounts will silently fail and produce garbage entries. That's 
> > > not ideal of course; we should fix that somehow.
> > 
> > > Note that this has nothing to do with the AppArmor discussion ...
> > 
> > This has everything to do with AA discussion.
> 
> How pathnames are used in /proc has *nothing* to do with AppAmor.
> 
> > You took unreliable, for-user-info kernel subsystem, and made security
> > subsystem depend on it. Oops.
> 
> Wrong. I said that the kernel uses pathnames for informational purposes only, 
> not that they are unreliable. Don't turn words around in my

Well, we know they are unreliable from other sources.

> The pathnames that d_path computes exactly reflect what the dcache knows. 
> (This requires the d_path fixes that are included in the AppArmor series and 
> have also been posted independently, and the reasons why these fixes are 
> needed are well explained in the mails.) The resulting pathnames are anything 
> but unreliable.

Yes?

Like... everything but AA works with very long paths?

Like... deleted files handling, where AA used to pick random name?

Like... races during tree renames, where AA may use name file never
ever had?
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-11 15:55                         ` Andreas Gruenbacher
  2007-06-11 19:02                           ` Serge E. Hallyn
@ 2007-06-12 13:13                           ` Stephen Smalley
  1 sibling, 0 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-12 13:13 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Mon, 2007-06-11 at 17:55 +0200, Andreas Gruenbacher wrote:
> On Monday 11 June 2007 16:33, Stephen Smalley wrote:
> > On Mon, 2007-06-11 at 01:10 +0200, Andreas Gruenbacher wrote:
> > > On Wednesday 06 June 2007 15:09, Stephen Smalley wrote:
> > > > On Mon, 2007-06-04 at 16:30 +0200, Andreas Gruenbacher wrote:
> > > > > On Monday 04 June 2007 15:12, Pavel Machek wrote:
> > > > > > How will kernel work with very long paths? I'd suspect some
> > > > > > problems, if path is 1MB long and I attempt to print it in /proc
> > > > > > somewhere.
> > > > >
> > > > > Pathnames are only used for informational purposes in the kernel,
> > > > > except in AppArmor of course.
> > > >
> > > > I don't mean this as a flame, but isn't the above statement the very
> > > > crux of this discussion?
> > >
> > > I think the question at the core of it all is, shall a pathname based
> > > security mechanism be allowed. I was under the impression that this
> > > question had already been answered affirmatively. If the answer here was
> > > no, then we could stop the entire discussion right there.
> >
> > There is a difference between using the pathname at the kernel/userland
> > interface as part of configuring a security mechanism and using it as
> > the basis for the runtime checking itself.
> 
> Yes, there is a difference. When I say pathname based security mechanism, I 
> literally mean a pathname based security mechanism, meaning the pathnames 
> determine the outcome o the decision. This includes designs that are based on 
> different abstractions internally, but the bahavior observable from 
> user-space must be the same (or else, it's a different model).
> 
> Unfortunately, translating pathnames to labels destroys this fundamental 
> abstraction. We explained why this is so in the following postings:
> 
> 	http://lkml.org/lkml/2007/6/9/94
> 	http://lkml.org/lkml/2007/6/10/141

I don't really see the specific reasons explained in the first posting;
the second one has a list of problems, but I'd question their validity:
- New files:  Adding the last component name as a further input to the
logic for determining the label of a new file would address many of the
concerns here.
- Renaming:  Do you honestly believe that renaming a file or directory
tree should automatically change its protection without explicit action
by the user/admin?  I don't, naturally, and Linux DAC certainly doesn't
work that way.  I view the change-protections-on-rename behavior of AA
as a flaw, not something to be emulated.
- New Policies:  So there may be more work to be done up front in the
label-based approach when developing policies.  Isn't that where you
want to front load the work?  Versus doing it at runtime?  Do you expect
users to be rewriting their policies constantly on their production
systems?
- File systems that do not support labels:  I'm a bit surprised that you
would advocate this given your experience in developing EA and ACL
support for local filesystems and NFS.  The pathname-based approach in
NFS seems even scarier than in the local case - the clients may have
different views of the namespace than one another or the server and the
potential for inconsistent views of the tree (particularly as it is
being modified) during access checks is only greater in the NFS case,
right?  It may be more expedient to implement, but is it the right
technical approach?

But possibly the larger question here is whether your abstraction is
fundamentally broken/leaky.  Even with your "native" implementation in
AA, you concede that there are cases where it breaks down, right?  e.g.
as the path returned by d_path may in fact differ from the path that was
looked up, as the tree can change between time-of-lookup and
time-of-path-generation?

> [cut here for lack of time right now -- will take another look later]

I'm hoping you'll ultimately respond to the questions I have raised (a
couple times now) about why this fundamentally differs from audit and/or
inotify, which take pathnames as part of configuring the mechanism but
do not generate them and match them on each access.

> 
> > > Without the vfsmounts propagated down you won't know the pathnames.
> > > Whether or not a different problem can be solved without the vfsmounts is
> > > not really relevant.
> >
> > Well, that presumes that your mechanism has to generate full pathnames
> > on each access check.  But even if so, you could be doing your checking
> > in the higher level code then where you have a vfsmount available.
> 
> The LSM hooks are pretty high-level, meant for being able to plug in different 
> access checks. That's the right level of abstraction. We just need the 
> vfsmounts passed down as well. That's what the bulk of common code patches 
> are there for.

Well, if you succeed in that, does that mean that the read-only bind
mount folks should go back to that approach?  Just looking for a little
bit of consistency among different efforts...

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-12 13:00                             ` Stephen Smalley
@ 2007-06-12 15:34                               ` Serge E. Hallyn
  2007-06-12  5:17                                 ` Karl MacMillan
  0 siblings, 1 reply; 240+ messages in thread
From: Serge E. Hallyn @ 2007-06-12 15:34 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Serge E. Hallyn, Andreas Gruenbacher, Pavel Machek, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

Quoting Stephen Smalley (sds@tycho.nsa.gov):
> On Mon, 2007-06-11 at 14:02 -0500, Serge E. Hallyn wrote:
> > Quoting Andreas Gruenbacher (agruen@suse.de):
> > > On Monday 11 June 2007 16:33, Stephen Smalley wrote:
> > > > On Mon, 2007-06-11 at 01:10 +0200, Andreas Gruenbacher wrote:
> > > > > On Wednesday 06 June 2007 15:09, Stephen Smalley wrote:
> > > > > > On Mon, 2007-06-04 at 16:30 +0200, Andreas Gruenbacher wrote:
> > > > > > > On Monday 04 June 2007 15:12, Pavel Machek wrote:
> > > > > > > > How will kernel work with very long paths? I'd suspect some
> > > > > > > > problems, if path is 1MB long and I attempt to print it in /proc
> > > > > > > > somewhere.
> > > > > > >
> > > > > > > Pathnames are only used for informational purposes in the kernel,
> > > > > > > except in AppArmor of course.
> > > > > >
> > > > > > I don't mean this as a flame, but isn't the above statement the very
> > > > > > crux of this discussion?
> > > > >
> > > > > I think the question at the core of it all is, shall a pathname based
> > > > > security mechanism be allowed. I was under the impression that this
> > > > > question had already been answered affirmatively. If the answer here was
> > 
> > That was the decision at ksummit last year, yes.
> > 
> > > > > no, then we could stop the entire discussion right there.
> > > >
> > > > There is a difference between using the pathname at the kernel/userland
> > > > interface as part of configuring a security mechanism and using it as
> > > > the basis for the runtime checking itself.
> > > 
> > > Yes, there is a difference. When I say pathname based security mechanism, I 
> > > literally mean a pathname based security mechanism, meaning the pathnames 
> > > determine the outcome o the decision. This includes designs that are based on 
> > > different abstractions internally, but the bahavior observable from 
> > > user-space must be the same (or else, it's a different model).
> > > 
> > > Unfortunately, translating pathnames to labels destroys this fundamental 
> > > abstraction. We explained why this is so in the following postings:
> > > 
> > > 	http://lkml.org/lkml/2007/6/9/94
> > > 	http://lkml.org/lkml/2007/6/10/141
> > > 
> > > > Further, there is a difference between generating and matching full
> > > > pathnames on each access vs. caching information in the parent dentry and
> > > > making decisions based on that cached information and the last
> > > > component-name.
> > > 
> > > Wait, you are mixing two issues here: access checks on existing files, and the 
> > > creation of new files. For AppArmor as it stands today the two are the same, 
> > > but when looking at emulating AppArmor using labels, they are not. Let's look 
> > > at things one at a time.
> > > 
> > > Generating and matching full pathnames on each access takes time, no question 
> > > about that. (In fact we are not checking on each access but only when 
> > > pathnames are involved, such as on open. Filehandle based operations do not 
> > > require access checks, but that's not a very important difference at this 
> > > level of discussion.) That's a quantitative statement though, not a 
> > > qualitative one: retrieving xattrs and checking labels also takes time; 
> > > additional checks are never for free. We find that doing the pathname checks 
> > > is easily fast enough. You may disagree, but then you don't have to use 
> > > AppArmor, and we are not standing in your way.
> > > 
> > > As far as new files are concerned, basing decisions on the parent dentry and 
> > > component name requires that you know where in the filesystem hierarchy this 
> > > dentry is located: with bind mounts, the same dentry shows up in multiple 
> > > locations in a process's namespace, corresponding to different pathnames. In 
> > > other words, to make the right decision, the dentry alone is not enough; it 
> > > takes a <dentry, vfsmount> pair. So there we are again.
> > > 
> > > >From the point on where you have a <dentry, vfsmount> pair of objects, you can 
> > > do two things: you can compute the full pathname and base your decision on 
> > > that, or you can do some caching to hopefully cut some of that work short 
> > > frequently enough to set off the additional cost. The difference between the 
> > > two approaches is quantitative -- if there is a difference in results, then 
> > > that's obviously a bug. I believe that caching could speed up things 
> > > measurably, but up to this point, neither I nor anybody else had the time to 
> > > look into it, and so we are not doing it -- not yet, any perhaps never at 
> > > all. It may be counter to your intuition, but doing those checks is not a big 
> > > issue.
> > 
> > My approach in DTE, which used pathnames to assign TE labels in the
> > kernel, was to use a 'shadow tree' to the vfsmnt+dentry tree, filled out
> > at policy load time to the depth of the deepest policy rule.  For the
> > behavior I was after, bind mounts were handled by storing pointers from
> > the new mount to the original, but the behavior AA wants would be
> > different.  Namespace clones are easily handled this way by copying the
> > cached pointers to the shadow tree.  And it was pretty fast.
> > 
> > When I talked about this with Tony last year, the biggest shortcoming to
> > use this for AA was the wildcards.  For instance, if there is a rule for
> > /var/log/HOSTS/*/messages, then when /var/log/HOSTS/sergelap/ is
> > created, a new rule would have to be created on the fly to tag
> > /var/log/HOSTS/sergelap/messages if it is created.  How to represent
> > that when only /var/log or /var/log/HOSTS exists at policy load time
> > would be, well, a fun problem to solve actually  :)
> 
> If we added support for named type transitions to SELinux, as proposed
> earlier by Kyle Moffett during this discussion, wouldn't that address
> that issue without needing a DTE-like approach?  The concept is to add

Haven't read his message, but based on what you laid out here sure, that
sounds good.  It still, like my dte approach, might have some trouble
with the wildcard/regex rules AA allows.  And while it might perfectly
reproduce my original DTE behavior, I don't think it does what AA wants
on bind mounts.  (Whether what AA wants for bind mounts makes sense I'm
still not convinced, especially with user mounts coming soon (or already
here?), but I'm staying out of that discussion for now)

> the last component name as a further input to the labeling decision for
> new files, in addition to the existing use of the creating process'
> label, the parent directory label, and the kind of file.  Then, you
> could have something like:
> type_transition <domain> var_log_hosts_t:file "messages" messages_t;
> 
> The last component name is already available, so that doesn't require
> any changes to LSM, and it would be a straightforward extension of
> SELinux to support the above - it doesn't change the model at all, just
> adds a further input to the new file labeling logic.

And eliminates the need for restorecond?

thanks,
-serge

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-10 21:05                   ` Pavel Machek
  2007-06-11  6:27                     ` david
@ 2007-06-12 17:03                     ` Lars Marowsky-Bree
  1 sibling, 0 replies; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-12 17:03 UTC (permalink / raw)
  To: Pavel Machek, david
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On 2007-06-10T23:05:47, Pavel Machek <pavel@ucw.cz> wrote:

> But you have that regex in _user_ space, in a place where policy
> is loaded into kernel.
> 
> AA has regex parser in _kernel_ space, which is very wrong.

That regex parser only applies user defined policy. The logical
connection between your two points doesn't exist.


Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-12  5:17                                 ` Karl MacMillan
@ 2007-06-12 19:00                                   ` Serge E. Hallyn
  0 siblings, 0 replies; 240+ messages in thread
From: Serge E. Hallyn @ 2007-06-12 19:00 UTC (permalink / raw)
  To: Karl MacMillan
  Cc: Serge E. Hallyn, Stephen Smalley, Andreas Gruenbacher,
	Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

Quoting Karl MacMillan (kmacmill@redhat.com):
> On Tue, 2007-06-12 at 10:34 -0500, Serge E. Hallyn wrote:
> > Quoting Stephen Smalley (sds@tycho.nsa.gov):
> 
> [...]
> 
> > > 
> > > If we added support for named type transitions to SELinux, as proposed
> > > earlier by Kyle Moffett during this discussion, wouldn't that address
> > > that issue without needing a DTE-like approach?  The concept is to add
> > 
> > Haven't read his message, but based on what you laid out here sure, that
> > sounds good.  It still, like my dte approach, might have some trouble
> > with the wildcard/regex rules AA allows.  And while it might perfectly
> > reproduce my original DTE behavior, I don't think it does what AA wants
> > on bind mounts.  (Whether what AA wants for bind mounts makes sense I'm
> > still not convinced, especially with user mounts coming soon (or already
> > here?), but I'm staying out of that discussion for now)
> > 
> > > the last component name as a further input to the labeling decision for
> > > new files, in addition to the existing use of the creating process'
> > > label, the parent directory label, and the kind of file.  Then, you
> > > could have something like:
> > > type_transition <domain> var_log_hosts_t:file "messages" messages_t;
> > > 
> > > The last component name is already available, so that doesn't require
> > > any changes to LSM, and it would be a straightforward extension of
> > > SELinux to support the above - it doesn't change the model at all, just
> > > adds a further input to the new file labeling logic.
> > 
> > And eliminates the need for restorecond?
> > 
> 
> Unlikely in the short term - restorecond is also used to reset contexts
> on critical files in /etc that might loose the context because tools
> used to update them are not correctly preserving contexts
> (e.g., /etc/mtab, etc/resolv.conf).

Confused - why wouldn't the new type_transition rule extension handle
that?

thanks,
-serge

> Actually - this whole notion restorecond as a critical component of
> SELinux because of a "new file problem" is pretty overblown. The default
> config file ships with:
> 
> /etc/resolv.conf
> /etc/samba/secrets.tdb
> /etc/mtab
> /var/run/utmp
> /var/log/wtmp
> ~/public_html
> ~/.mozilla/plugins/libflashplayer.so
> 
> So the only things that would be helped by type_transition rules with a 
> name component would be public_html and libflashplayer.so.
> 
> Karl
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 38/45] AppArmor: Module and LSM hooks
  2007-06-11 14:33                       ` Stephen Smalley
  2007-06-11 15:55                         ` Andreas Gruenbacher
@ 2007-06-12 23:50                         ` Andreas Gruenbacher
  1 sibling, 0 replies; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-12 23:50 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Monday 11 June 2007 16:33, Stephen Smalley wrote:
>From a userland perspective, audit and inotify allow you to specify
> watches on pathnames, and those watches trigger actions by the audit and
> inotify subsystems when those files are accessed.  The kernel mechanism
> however is inode-based, not pathname-based; the pathname is merely
> looked up when the watch is added and mapped to an inode.  That's my
> point - why should AA be different?

Audit watches are not entirely object based (contrary to what the man page 
says): with simple file renames the watches sticks with the names; with 
directory renames, watches below the directory get dropped. That's rather 
weird, and I would say bad for audit.

Inotify really watches objects. I can imagine cases where this is exactly what 
you want, and others where this is exactly what you don't want -- it's pick 
your poison.

AppArmor deliberately is pathname based. There are good reasons for that, and 
we really, definitely want this pathname based model, with all its benefits 
and disadvantages. Arguing that AppArmor shouldn't be pathname based because 
other parts of the kernel try to balance names vs. objects differently, and 
not even always the same way either, is pretty narrow-minded.

If one thing is clear from this entire discussion, it is that there is no 
agreement on the One True Model, and different solutions are being used.

> Would you really recommend that audit or inotify call d_path() on each
> open and glob match the result against a list of audit or inotify watches?

I don't remember doing so.

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09  8:03                               ` david
  2007-06-09  8:37                                 ` Sean
@ 2007-06-14 17:01                                 ` Pavel Machek
  1 sibling, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-14 17:01 UTC (permalink / raw)
  To: david; +Cc: Sean, Tetsuo Handa, linux-kernel, linux-security-module

Hi!

> I also don't care about the details of how it gets 
> implemented, but when the AA people have a working 
> implementation, and the SELinux people are strongly 
> opposed to the concept, I don't see any advantage in 

Actually, SELinux people 'liked' the concept -- they are willing to
extend SELinux to handle new files better. And not only SELinux people
are opposed to AA.

> if the SELinux people had responded to the announcement 
> of AA with "that's a nice idea, if we add these snippits 
> from your code to SELinux then we can do the same thing" 
> it would be a very different story.

It was something like 'is there description of AA security model? We'd
like to take a look if we can do that within SELinux'. I tried to
forward them pdf, but it was more AA implementation description (not
AA model description) so it was probably not helpful.

So yes, SELinux people want to help.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-11  6:27                     ` david
@ 2007-06-14 19:16                       ` Jack Stone
  2007-06-15  0:18                         ` david
  0 siblings, 1 reply; 240+ messages in thread
From: Jack Stone @ 2007-06-14 19:16 UTC (permalink / raw)
  To: david
  Cc: greg, agruen, sds, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel, pavel

david@lang.hm wrote:
> On Sun, 10 Jun 2007, Pavel Machek wrote:
>> But you have that regex in _user_ space, in a place where policy
>> is loaded into kernel.
> 
> then the kernel is going to have to call out to userspace every time a
> file is created or renamed and the policy is going to be enforced
> incorrectly until userspace finished labeling/relabeling whatever is
> moved. building this sort of race condigion for security into the kernel
> is highly questionable at best.
> 
>> AA has regex parser in _kernel_ space, which is very wrong.
> 
> see Linus' rants about why it's not automaticaly the best thing to move
> functionality into userspace.
> 
> remember that the files covered by an AA policy can change as files are
> renamed. this isn't the case with SELinux so it doesn't have this sort
> of problem.

How about using the inotify interface on / to watch for file changes and
 updating the SELinux policies on the fly. This could be done from a
userspace daemon and should require minimal SELinux changes.

The only possible problems I can see are the (hopefully) small gap
between the file change and updating the policy and the performance
problems of watching the whole system for changes.

Just my $0.02.

Jack

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-14 19:16                       ` Jack Stone
@ 2007-06-15  0:18                         ` david
  2007-06-15 17:01                           ` Greg KH
  0 siblings, 1 reply; 240+ messages in thread
From: david @ 2007-06-15  0:18 UTC (permalink / raw)
  To: Jack Stone
  Cc: greg, agruen, sds, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel, pavel

On Thu, 14 Jun 2007, Jack Stone wrote:

> david@lang.hm wrote:
>> On Sun, 10 Jun 2007, Pavel Machek wrote:
>>> But you have that regex in _user_ space, in a place where policy
>>> is loaded into kernel.
>>
>> then the kernel is going to have to call out to userspace every time a
>> file is created or renamed and the policy is going to be enforced
>> incorrectly until userspace finished labeling/relabeling whatever is
>> moved. building this sort of race condigion for security into the kernel
>> is highly questionable at best.
>>
>>> AA has regex parser in _kernel_ space, which is very wrong.
>>
>> see Linus' rants about why it's not automaticaly the best thing to move
>> functionality into userspace.
>>
>> remember that the files covered by an AA policy can change as files are
>> renamed. this isn't the case with SELinux so it doesn't have this sort
>> of problem.
>
> How about using the inotify interface on / to watch for file changes and
> updating the SELinux policies on the fly. This could be done from a
> userspace daemon and should require minimal SELinux changes.
>
> The only possible problems I can see are the (hopefully) small gap
> between the file change and updating the policy and the performance
> problems of watching the whole system for changes.

as was mentioned by someone else, if you rename a directory this can 
result in millions of files that need to be relabeled (or otherwise have 
the policy changed for them)

that can take a significant amount of time to do.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-09 18:37                               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Casey Schaufler
@ 2007-06-15 13:36                                 ` Pavel Machek
  0 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-15 13:36 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Sean, david, Tetsuo Handa, linux-kernel, linux-security-module

Hi!

> > The question is: why not just extend SELinux to include AA functionality
> > rather than doing a whole new subsystem.
> 
> Because, as hard as it seems for some people to believe,
> not everyone wants Type Enforcement. SELinux is a fine
> implementation of type enforcement, but if you don't want
> what it does it would be silly to require that it be
> used in order to accomplish something else, like name based
> access control.
> 
> If the same things made everyone feel "secure" there would be
> no optional security facilities (audit, cryptfs, /dev/random, ACLs).
> It appears that the AA folks are sufficiently unimpressed with
> SELinux they want to do something different. I understand that

Actually, no. AA was started at time when SELinux was very different
from today, and now AA people have installed base of 'happy users'
they are trying to support.
							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-10 17:09             ` Crispin Cowan
@ 2007-06-15 16:50               ` Greg KH
  2007-06-15 18:01                 ` Casey Schaufler
                                   ` (2 more replies)
  0 siblings, 3 replies; 240+ messages in thread
From: Greg KH @ 2007-06-15 16:50 UTC (permalink / raw)
  To: Crispin Cowan
  Cc: Andreas Gruenbacher, Stephen Smalley, Pavel Machek, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Sun, Jun 10, 2007 at 10:09:18AM -0700, Crispin Cowan wrote:
> Andreas Gruenbacher wrote:
> > On Saturday 09 June 2007 02:17, Greg KH wrote:
> >   
> >> On Sat, Jun 09, 2007 at 12:03:57AM +0200, Andreas Gruenbacher wrote:
> >>     
> >>> AppArmor is meant to be relatively easy to understand, manage, and
> >>>  customize, and introducing a labels layer wouldn't help these goals.
> >>>       
> >> Woah, that describes the userspace side of AA just fine, it means
> >> nothing when it comes to the in-kernel implementation. There is no 
> >> reason that you can't implement the same functionality using some
> >> totally different in-kernel solution if possible.
> >>     
> > I agree that the in-kernel implementation could use different abstractions 
> > than user-space, provided that the underlying implementation details can be 
> > hidden well enough. The key phrase here is "if possible", and in fact "if 
> > possible" is much too strong: very many things in software are possible, 
> > including user-space drives and a stable kernel module ABI. Some things make 
> > sense; others are genuinely bad ideas while still possible.
> >   
> In particular, to layer AppArmor on top of SELinux, the following
> problems must be addressed:
> 
>     * New files: when a file is created, it is labeled according to the
>       type of the creating process and the type of the parent directory.
>       Applications can also use libselinux to use application logic to
>       relabel the file, but that is not 'mandatory' policy, and fails in
>       cases like cp and mv. AppArmor lets you create a policy that e..g
>       says "/home/*/.plan r" to permit fingerd to read everyone's .plan
>       file, should it ever exist, and you cannot emulate that with SELinux.

A daemon using inotify can "instantly"[1] detect this and label the file
properly if it shows up.

>     * Renamed Files: Renaming a file changes the policy with respect to
>       that file in AA. To emulate this in SELinux, you would have to
>       have a way to instantly re-label the file upon rename.

Same daemon can do the re-label.

>     * Renamed Directory trees: The above problem is compounded with
>       directory trees. Changing the name at the top of a large, bushy
>       tree can require instant relabeling of millions of files.

Same daemon can do this.  And yes, it might take a ammount of time, but
the times that this happens in "real-life" on a "production" server is
quite small, if at all.

>     * New Policies: The SEEdit approach of compiling AA profiles into
>       SELinux labels involves computing the partition set of files, so
>       that each element of the partition set is unique, and corresponds
>       to all the policies that treat every file in the element
>       identically. If you create a new profile that touches *some* of
>       the files in such an element, then you have to split that
>       synthetic label, re-compute the partition set, and re-label the
>       file system.

Again, same daemon can handle this logic.

>     * File Systems That Do Not Support Labels: The most important being
>       NFS3 and FAT. Because they do not support labels at all, SELinux
>       has to give you an all-or-nothing access control on the entire
>       remote volume. AA can give you nuanced access control in these
>       file systems.

SELinux already provides support for the whole mounted filesystem,
which, in real-life testing, seems to be quite sufficient.  Also, the
SELinux developers are working on some changes to make this a bit more
fine-grained.

See also Stephan's previous comments about NFSv3 client directories and
multiple views having the potential to cause a lot of havoc.

> You could support all of these features in SELinux, but only by adding
> an in-kernel file matching mechanism similar to AppArmor.

I don't think that is necessary at all, see above for why.

> It would basically load an AppArmor policy into the kernel, label
> files as they are brought from disk into the cache, and then use
> SELinux to do the access controls.

No, do the labeling in userspace with a daemon using inotify to handle
the changing of the files around.

Or has this whole idea of a daemon been disproved already with a
prototype somewhere that failed?  If not, a simple test app would not be
that hard to hack up.  Maybe I'll see if I can do it during the week of
June 24 :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15  0:18                         ` david
@ 2007-06-15 17:01                           ` Greg KH
  0 siblings, 0 replies; 240+ messages in thread
From: Greg KH @ 2007-06-15 17:01 UTC (permalink / raw)
  To: david
  Cc: Jack Stone, agruen, sds, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel, pavel

On Thu, Jun 14, 2007 at 05:18:43PM -0700, david@lang.hm wrote:
>  On Thu, 14 Jun 2007, Jack Stone wrote:
> 
> > david@lang.hm wrote:
> >> On Sun, 10 Jun 2007, Pavel Machek wrote:
> >>> But you have that regex in _user_ space, in a place where policy
> >>> is loaded into kernel.
> >>
> >> then the kernel is going to have to call out to userspace every time a
> >> file is created or renamed and the policy is going to be enforced
> >> incorrectly until userspace finished labeling/relabeling whatever is
> >> moved. building this sort of race condigion for security into the kernel
> >> is highly questionable at best.
> >>
> >>> AA has regex parser in _kernel_ space, which is very wrong.
> >>
> >> see Linus' rants about why it's not automaticaly the best thing to move
> >> functionality into userspace.
> >>
> >> remember that the files covered by an AA policy can change as files are
> >> renamed. this isn't the case with SELinux so it doesn't have this sort
> >> of problem.
> >
> > How about using the inotify interface on / to watch for file changes and
> > updating the SELinux policies on the fly. This could be done from a
> > userspace daemon and should require minimal SELinux changes.
> >
> > The only possible problems I can see are the (hopefully) small gap
> > between the file change and updating the policy and the performance
> > problems of watching the whole system for changes.
> 
>  as was mentioned by someone else, if you rename a directory this can result 
>  in millions of files that need to be relabeled (or otherwise have the policy 
>  changed for them)
> 
>  that can take a significant amount of time to do.

So?  The number of "real-world" times that this happens is probably
non-existant on a "production" server.  And if you are doing this on a
developer machine, then yes, there might be some slow-down, but no more
than is currently happening with tools like Beagle that people are
already shipping and supporting in "enterprise" solutions.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 16:50               ` Greg KH
@ 2007-06-15 18:01                 ` Casey Schaufler
  2007-06-15 18:15                   ` Stephen Smalley
  2007-06-15 20:06                 ` Pavel Machek
  2007-06-16 15:44                 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
  2 siblings, 1 reply; 240+ messages in thread
From: Casey Schaufler @ 2007-06-15 18:01 UTC (permalink / raw)
  To: Greg KH, Crispin Cowan
  Cc: Andreas Gruenbacher, Stephen Smalley, Pavel Machek, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel


--- Greg KH <greg@kroah.com> wrote:


> A daemon using inotify can "instantly"[1] detect this and label the file
> properly if it shows up.

In our 1995 B1 evaluation of Trusted Irix we were told in no
uncertain terms that such a solution was not acceptable under
the TCSEC requirements. Detection and relabel on an unlocked
object creates an obvious window for exploitation. We were told
that such a scheme would be considered a design flaw.

I understand that some of the Common Criteria labs are less
aggressive regarding chasing down these issues than the NCSC
teams were. It might not prevent an evaluation from completing
today. It is still hard to explain why it's ok to have a file
that's labeled incorrectly _even briefly_. It is the systems
job to ensure that that does not happen.


Casey Schaufler
casey@schaufler-ca.com

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 18:01                 ` Casey Schaufler
@ 2007-06-15 18:15                   ` Stephen Smalley
  2007-06-15 20:43                     ` Casey Schaufler
  0 siblings, 1 reply; 240+ messages in thread
From: Stephen Smalley @ 2007-06-15 18:15 UTC (permalink / raw)
  To: casey
  Cc: Greg KH, Crispin Cowan, Andreas Gruenbacher, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Fri, 2007-06-15 at 11:01 -0700, Casey Schaufler wrote:
> --- Greg KH <greg@kroah.com> wrote:
> 
> 
> > A daemon using inotify can "instantly"[1] detect this and label the file
> > properly if it shows up.
> 
> In our 1995 B1 evaluation of Trusted Irix we were told in no
> uncertain terms that such a solution was not acceptable under
> the TCSEC requirements. Detection and relabel on an unlocked
> object creates an obvious window for exploitation. We were told
> that such a scheme would be considered a design flaw.
> 
> I understand that some of the Common Criteria labs are less
> aggressive regarding chasing down these issues than the NCSC
> teams were. It might not prevent an evaluation from completing
> today. It is still hard to explain why it's ok to have a file
> that's labeled incorrectly _even briefly_. It is the systems
> job to ensure that that does not happen.

Um, Casey, he is talking about how to emulate AppArmor behavior on a
label-based system like SELinux, not meeting B1 or LSPP or anything like
that (which AppArmor can't do regardless).  As far as general issue
goes, if your policy is configured such that the new file gets the most
restrictive label possible at creation time and then the daemon relabels
it to a less restrictive label if appropriate, then there is no actual
window of exposure.

Also, there is such a daemon, restorecond, in SELinux (policycoreutils)
although we avoid relying on it for anything security-critical
naturally.  And one could introduce the named type transition concept
that has been discussed in this thread without much difficulty to
selinux.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 16:50               ` Greg KH
  2007-06-15 18:01                 ` Casey Schaufler
@ 2007-06-15 20:06                 ` Pavel Machek
  2007-06-15 21:11                   ` Greg KH
  2007-06-15 23:33                   ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Seth Arnold
  2007-06-16 15:44                 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
  2 siblings, 2 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-15 20:06 UTC (permalink / raw)
  To: Greg KH
  Cc: Crispin Cowan, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

Hi!

And before you scream "races", take a look. It does not actually add
them:

> > > I agree that the in-kernel implementation could use different abstractions 
> > > than user-space, provided that the underlying implementation details can be 
> > > hidden well enough. The key phrase here is "if possible", and in fact "if 
> > > possible" is much too strong: very many things in software are possible, 
> > > including user-space drives and a stable kernel module ABI. Some things make 
> > > sense; others are genuinely bad ideas while still possible.
> > >   
> > In particular, to layer AppArmor on top of SELinux, the following
> > problems must be addressed:
> > 
> >     * New files: when a file is created, it is labeled according to the
> >       type of the creating process and the type of the parent directory.
> >       Applications can also use libselinux to use application logic to
> >       relabel the file, but that is not 'mandatory' policy, and fails in
> >       cases like cp and mv. AppArmor lets you create a policy that e..g
> >       says "/home/*/.plan r" to permit fingerd to read everyone's .plan
> >       file, should it ever exist, and you cannot emulate that with SELinux.
> 
> A daemon using inotify can "instantly"[1] detect this and label the file
> properly if it shows up.

Or just create the files with restrictive labels by default. That way
you "fail closed".

> >     * Renamed Files: Renaming a file changes the policy with respect to
> >       that file in AA. To emulate this in SELinux, you would have to
> >       have a way to instantly re-label the file upon rename.
> 
> Same daemon can do the re-label.

...and no, race there is not important. Attacker may have opened the
file under old name and is keeping open file descriptor. So this does
not add a new race relative to AA.

> >     * Renamed Directory trees: The above problem is compounded with
> >       directory trees. Changing the name at the top of a large, bushy
> >       tree can require instant relabeling of millions of files.
> 
> Same daemon can do this.  And yes, it might take a ammount of time, but
> the times that this happens in "real-life" on a "production" server is
> quite small, if at all.

And now, if you move a tree, there will be old labels for a while. But
this does not matter, because attacker could be keeping file
descriptors.

Only case where attacker _can't_ be keeping file descriptors is newly
created files in recently moved tree. But as you already create files
with restrictive permissions, that's okay.

Yes, you may get some -EPERM during the tree move, but AA has that
problem already, see that "when madly moving trees we sometimes
construct path file never ever had".

								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 18:15                   ` Stephen Smalley
@ 2007-06-15 20:43                     ` Casey Schaufler
  2007-06-15 21:14                       ` Greg KH
  2007-06-18 12:47                       ` Stephen Smalley
  0 siblings, 2 replies; 240+ messages in thread
From: Casey Schaufler @ 2007-06-15 20:43 UTC (permalink / raw)
  To: Stephen Smalley, casey
  Cc: Greg KH, Crispin Cowan, Andreas Gruenbacher, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel


--- Stephen Smalley <sds@tycho.nsa.gov> wrote:

> On Fri, 2007-06-15 at 11:01 -0700, Casey Schaufler wrote:
> > --- Greg KH <greg@kroah.com> wrote:
> > 
> > 
> > > A daemon using inotify can "instantly"[1] detect this and label the file
> > > properly if it shows up.
> > 
> > In our 1995 B1 evaluation of Trusted Irix we were told in no
> > uncertain terms that such a solution was not acceptable under
> > the TCSEC requirements. Detection and relabel on an unlocked
> > object creates an obvious window for exploitation. We were told
> > that such a scheme would be considered a design flaw.
> > 
> > I understand that some of the Common Criteria labs are less
> > aggressive regarding chasing down these issues than the NCSC
> > teams were. It might not prevent an evaluation from completing
> > today. It is still hard to explain why it's ok to have a file
> > that's labeled incorrectly _even briefly_. It is the systems
> > job to ensure that that does not happen.
> 
> Um, Casey, he is talking about how to emulate AppArmor behavior on a
> label-based system like SELinux,

Yes. What I'm saying (or trying to) is that such an implementation
would be flawed by design.

> not meeting B1 or LSPP or anything like that
> (which AppArmor can't do regardless).

We're not talking about an implementation based on AppArmor. As
you point out, we're talking about implementing name based access
control as an extension of SELinux.

> As far as general issue
> goes, if your policy is configured such that the new file gets the most
> restrictive label possible at creation time and then the daemon relabels
> it to a less restrictive label if appropriate, then there is no actual
> window of exposure.

Is it general practice to configure policy such that "the new file gets
the most restrictive label possible at creation time"? I confess that
my understanding of the current practice in policy generation is based
primarily on a shouted conversation in a crowded Irish pub.

> Also, there is such a daemon, restorecond, in SELinux (policycoreutils)
> although we avoid relying on it for anything security-critical
> naturally.

Yes, I am aware of restorecond. I find the need for restorecond troubling.

> And one could introduce the named type transition concept
> that has been discussed in this thread without much difficulty to
> selinux.

Yup, I see that once you accept the notion that it is OK for a
file to be misslabeled for a bit and that having a fixxerupperd
is sufficient it all falls out.

My point is that there is a segment of the security community
that had not found this acceptable, even under the conditions
outlined. If it meets your needs, I say run with it.


Casey Schaufler
casey@schaufler-ca.com

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 20:06                 ` Pavel Machek
@ 2007-06-15 21:11                   ` Greg KH
  2007-06-15 21:42                     ` James Morris
  2007-06-15 23:30                     ` Crispin Cowan
  2007-06-15 23:33                   ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Seth Arnold
  1 sibling, 2 replies; 240+ messages in thread
From: Greg KH @ 2007-06-15 21:11 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Crispin Cowan, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Fri, Jun 15, 2007 at 10:06:23PM +0200, Pavel Machek wrote:
> Hi!
> 
> And before you scream "races", take a look. It does not actually add
> them:

Hey, I never screamed that at all, in fact, I completly agree with you
:)

> > > > I agree that the in-kernel implementation could use different abstractions 
> > > > than user-space, provided that the underlying implementation details can be 
> > > > hidden well enough. The key phrase here is "if possible", and in fact "if 
> > > > possible" is much too strong: very many things in software are possible, 
> > > > including user-space drives and a stable kernel module ABI. Some things make 
> > > > sense; others are genuinely bad ideas while still possible.
> > > >   
> > > In particular, to layer AppArmor on top of SELinux, the following
> > > problems must be addressed:
> > > 
> > >     * New files: when a file is created, it is labeled according to the
> > >       type of the creating process and the type of the parent directory.
> > >       Applications can also use libselinux to use application logic to
> > >       relabel the file, but that is not 'mandatory' policy, and fails in
> > >       cases like cp and mv. AppArmor lets you create a policy that e..g
> > >       says "/home/*/.plan r" to permit fingerd to read everyone's .plan
> > >       file, should it ever exist, and you cannot emulate that with SELinux.
> > 
> > A daemon using inotify can "instantly"[1] detect this and label the file
> > properly if it shows up.
> 
> Or just create the files with restrictive labels by default. That way
> you "fail closed".

>From my limited knowledge of SELinux, this is the default today so this
would happen by default.  Anyone with more SELinux experience want to
verify or fix my understanding of this?

> > >     * Renamed Files: Renaming a file changes the policy with respect to
> > >       that file in AA. To emulate this in SELinux, you would have to
> > >       have a way to instantly re-label the file upon rename.
> > 
> > Same daemon can do the re-label.
> 
> ...and no, race there is not important. Attacker may have opened the
> file under old name and is keeping open file descriptor. So this does
> not add a new race relative to AA.

Agreed.

> > >     * Renamed Directory trees: The above problem is compounded with
> > >       directory trees. Changing the name at the top of a large, bushy
> > >       tree can require instant relabeling of millions of files.
> > 
> > Same daemon can do this.  And yes, it might take a ammount of time, but
> > the times that this happens in "real-life" on a "production" server is
> > quite small, if at all.
> 
> And now, if you move a tree, there will be old labels for a while. But
> this does not matter, because attacker could be keeping file
> descriptors.

Agreed.

> Only case where attacker _can't_ be keeping file descriptors is newly
> created files in recently moved tree. But as you already create files
> with restrictive permissions, that's okay.
> 
> Yes, you may get some -EPERM during the tree move, but AA has that
> problem already, see that "when madly moving trees we sometimes
> construct path file never ever had".

Exactly.

I can't think of a "real world" use of moving directory trees around
that this would come up in as a problem.  Maybe a source code control
system might have this issue for the server, but in a second or two
everything would be working again as the new files would be relabled
correctly.

Can anyone else see a problem with this that I'm just being foolish and
missing?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 20:43                     ` Casey Schaufler
@ 2007-06-15 21:14                       ` Greg KH
  2007-06-15 21:28                         ` Karl MacMillan
  2007-06-15 22:37                         ` Casey Schaufler
  2007-06-18 12:47                       ` Stephen Smalley
  1 sibling, 2 replies; 240+ messages in thread
From: Greg KH @ 2007-06-15 21:14 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Stephen Smalley, Crispin Cowan, Andreas Gruenbacher,
	Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, Jun 15, 2007 at 01:43:31PM -0700, Casey Schaufler wrote:
> 
> Yup, I see that once you accept the notion that it is OK for a
> file to be misslabeled for a bit and that having a fixxerupperd
> is sufficient it all falls out.
> 
> My point is that there is a segment of the security community
> that had not found this acceptable, even under the conditions
> outlined. If it meets your needs, I say run with it.

If that segment feels that way, then I imagine AA would not meet their
requirements today due to file handles and other ways of passing around
open files, right?

So, would SELinux today (without this AA-like daemon) fit the
requirements of this segment?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 21:14                       ` Greg KH
@ 2007-06-15 21:28                         ` Karl MacMillan
  2007-06-15 21:44                           ` Greg KH
  2007-06-15 22:37                         ` Casey Schaufler
  1 sibling, 1 reply; 240+ messages in thread
From: Karl MacMillan @ 2007-06-15 21:28 UTC (permalink / raw)
  To: Greg KH
  Cc: Casey Schaufler, Stephen Smalley, Crispin Cowan,
	Andreas Gruenbacher, Pavel Machek, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 2007-06-15 at 14:14 -0700, Greg KH wrote:
> On Fri, Jun 15, 2007 at 01:43:31PM -0700, Casey Schaufler wrote:
> > 
> > Yup, I see that once you accept the notion that it is OK for a
> > file to be misslabeled for a bit and that having a fixxerupperd
> > is sufficient it all falls out.
> > 
> > My point is that there is a segment of the security community
> > that had not found this acceptable, even under the conditions
> > outlined. If it meets your needs, I say run with it.
> 
> If that segment feels that way, then I imagine AA would not meet their
> requirements today due to file handles and other ways of passing around
> open files, right?
> 
> So, would SELinux today (without this AA-like daemon) fit the
> requirements of this segment?
> 

Yes - RHEL 5 is going through CC evaluations for LSPP, CAPP, and RBAC
using the features of SELinux where appropriate.

Karl




^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 21:11                   ` Greg KH
@ 2007-06-15 21:42                     ` James Morris
  2007-06-15 23:50                       ` Greg KH
  2007-06-15 23:30                     ` Crispin Cowan
  1 sibling, 1 reply; 240+ messages in thread
From: James Morris @ 2007-06-15 21:42 UTC (permalink / raw)
  To: Greg KH
  Cc: Pavel Machek, Crispin Cowan, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, 15 Jun 2007, Greg KH wrote:

> > Or just create the files with restrictive labels by default. That way
> > you "fail closed".
> 
> From my limited knowledge of SELinux, this is the default today so this
> would happen by default.  Anyone with more SELinux experience want to
> verify or fix my understanding of this?

This is entirely controllable via policy.  That is, you specify that newly 
create files are labeled to something safe (enforced atomically at the 
kernel level), and then your userland relabeler would be invoked via 
inotify to relabel based on your userland pathname specification.

This labeling policy can be as granular as you wish, from the entire 
filesystem to a single file.  It can also be applied depending on the 
process which created the file and the directory its created in, ranging 
from all processes and all directories, to say, just those running as 
user_t in directories labeled as public_html_t (or whatever).



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 21:28                         ` Karl MacMillan
@ 2007-06-15 21:44                           ` Greg KH
  2007-06-15 22:24                             ` Karl MacMillan
  0 siblings, 1 reply; 240+ messages in thread
From: Greg KH @ 2007-06-15 21:44 UTC (permalink / raw)
  To: Karl MacMillan
  Cc: Casey Schaufler, Stephen Smalley, Crispin Cowan,
	Andreas Gruenbacher, Pavel Machek, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, Jun 15, 2007 at 05:28:35PM -0400, Karl MacMillan wrote:
> On Fri, 2007-06-15 at 14:14 -0700, Greg KH wrote:
> > On Fri, Jun 15, 2007 at 01:43:31PM -0700, Casey Schaufler wrote:
> > > 
> > > Yup, I see that once you accept the notion that it is OK for a
> > > file to be misslabeled for a bit and that having a fixxerupperd
> > > is sufficient it all falls out.
> > > 
> > > My point is that there is a segment of the security community
> > > that had not found this acceptable, even under the conditions
> > > outlined. If it meets your needs, I say run with it.
> > 
> > If that segment feels that way, then I imagine AA would not meet their
> > requirements today due to file handles and other ways of passing around
> > open files, right?
> > 
> > So, would SELinux today (without this AA-like daemon) fit the
> > requirements of this segment?
> > 
> 
> Yes - RHEL 5 is going through CC evaluations for LSPP, CAPP, and RBAC
> using the features of SELinux where appropriate.

Great, but is there the requirement in the CC stuff such that this type
of "delayed re-label" that an AA-like daemon would need to do cause that
model to not be able to be certified like your SELinux implementation
is?

As I'm guessing the default "label" for things like this already work
properly for SELinux, I figure we should be safe, but I don't know those
requirements at all.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 21:44                           ` Greg KH
@ 2007-06-15 22:24                             ` Karl MacMillan
  2007-06-18 13:33                               ` Stephen Smalley
  0 siblings, 1 reply; 240+ messages in thread
From: Karl MacMillan @ 2007-06-15 22:24 UTC (permalink / raw)
  To: Greg KH
  Cc: Casey Schaufler, Stephen Smalley, Crispin Cowan,
	Andreas Gruenbacher, Pavel Machek, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 2007-06-15 at 14:44 -0700, Greg KH wrote:
> On Fri, Jun 15, 2007 at 05:28:35PM -0400, Karl MacMillan wrote:
> > On Fri, 2007-06-15 at 14:14 -0700, Greg KH wrote:
> > > On Fri, Jun 15, 2007 at 01:43:31PM -0700, Casey Schaufler wrote:
> > > > 
> > > > Yup, I see that once you accept the notion that it is OK for a
> > > > file to be misslabeled for a bit and that having a fixxerupperd
> > > > is sufficient it all falls out.
> > > > 
> > > > My point is that there is a segment of the security community
> > > > that had not found this acceptable, even under the conditions
> > > > outlined. If it meets your needs, I say run with it.
> > > 
> > > If that segment feels that way, then I imagine AA would not meet their
> > > requirements today due to file handles and other ways of passing around
> > > open files, right?
> > > 
> > > So, would SELinux today (without this AA-like daemon) fit the
> > > requirements of this segment?
> > > 
> > 
> > Yes - RHEL 5 is going through CC evaluations for LSPP, CAPP, and RBAC
> > using the features of SELinux where appropriate.
> 
> Great, but is there the requirement in the CC stuff such that this type
> of "delayed re-label" that an AA-like daemon would need to do cause that
> model to not be able to be certified like your SELinux implementation
> is?
> 

There are two things:

1) relabeling (non-tranquility) is very problematic in general because
revocation is hard (and non-solved in Linux). So you would have to
address concerns about that.

2) Whether this would pass certification depends on a lot of factors
(like the specific requirements - CC is just a process not a single set
of requirements). I don't know enough to really guess.

More to the point, though, the requirements in those documents are
outdated at best. I don't think it is worth worrying over.

> As I'm guessing the default "label" for things like this already work
> properly for SELinux, I figure we should be safe, but I don't know those
> requirements at all.
> 

Probably not - you would likely want it to be a label that can't be read
or written by anything, only relabeled by the daemon.

Karl



^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 21:14                       ` Greg KH
  2007-06-15 21:28                         ` Karl MacMillan
@ 2007-06-15 22:37                         ` Casey Schaufler
  1 sibling, 0 replies; 240+ messages in thread
From: Casey Schaufler @ 2007-06-15 22:37 UTC (permalink / raw)
  To: Greg KH
  Cc: Stephen Smalley, Crispin Cowan, Andreas Gruenbacher,
	Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel


--- Greg KH <greg@kroah.com> wrote:

> On Fri, Jun 15, 2007 at 01:43:31PM -0700, Casey Schaufler wrote:
> > 
> > Yup, I see that once you accept the notion that it is OK for a
> > file to be misslabeled for a bit and that having a fixxerupperd
> > is sufficient it all falls out.
> > 
> > My point is that there is a segment of the security community
> > that had not found this acceptable, even under the conditions
> > outlined. If it meets your needs, I say run with it.
> 
> If that segment feels that way, then I imagine AA would not meet their
> requirements today due to file handles and other ways of passing around
> open files, right?

That segment is itself divided (think the "Judean Peoples Front"
and the "Peoples Front of Judea") on many issues, but as it has
always put correctness over ease of use I would expect AppArmor to
have a tough roe to hoe. There are other segments for which AppArmor
may well be appealing, and those segments have always been much
larger than Judea.

> So, would SELinux today (without this AA-like daemon) fit the
> requirements of this segment?

The JPF is head over heels in love with SELinux, restorecond and all.
The PFJ has some issues, but will most likely go along with the JPF
in part because the JPF is bringing the beer and besides, what are
their alternatives today? The PJF ("that's him, over there") is still
stunned by some of what SELinux accepts as normal (restorecond, 400,000
line "policy" definitions with embedded wildcards) and spends a lot
of time chanting the TCB Principle in hopes that it will help, but
no lightning strikes from above to date.

But you knew that. I'm an advocate of making a variety of alternates
available which is why I had originally proposed the authoritative
hooks version of the LSM and why I don't believe in rolling every
possible security facility into SELinux. I also believe in warning
people of pitfalls before they've impaled themselves on the spikes,
but some people gotta have the experience. Just trying to help.


Casey Schaufler
casey@schaufler-ca.com

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 21:11                   ` Greg KH
  2007-06-15 21:42                     ` James Morris
@ 2007-06-15 23:30                     ` Crispin Cowan
  2007-06-15 23:49                       ` Greg KH
                                         ` (2 more replies)
  1 sibling, 3 replies; 240+ messages in thread
From: Crispin Cowan @ 2007-06-15 23:30 UTC (permalink / raw)
  To: Greg KH
  Cc: Pavel Machek, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

Greg KH wrote:
> On Fri, Jun 15, 2007 at 10:06:23PM +0200, Pavel Machek wrote:
>   
>>>>     * Renamed Directory trees: The above problem is compounded with
>>>>       directory trees. Changing the name at the top of a large, bushy
>>>>       tree can require instant relabeling of millions of files.
>>>>         
>>> Same daemon can do this.  And yes, it might take a ammount of time, but
>>> the times that this happens in "real-life" on a "production" server is
>>> quite small, if at all.
>>>       
>> And now, if you move a tree, there will be old labels for a while. But
>> this does not matter, because attacker could be keeping file
>> descriptors.
>>     
> Agreed.
>   
We have built a label-based AA prototype. It fails because there is no
reasonable way to address the tree renaming problem.

>> Only case where attacker _can't_ be keeping file descriptors is newly
>> created files in recently moved tree. But as you already create files
>> with restrictive permissions, that's okay.
>>
>> Yes, you may get some -EPERM during the tree move, but AA has that
>> problem already, see that "when madly moving trees we sometimes
>> construct path file never ever had".
>>     
> Exactly.
>   
You are remembering old behavior. The current AppArmor generates only
correct and consistent paths. If a process has an open file descriptor
to such a file, they will retain access to it, as we described here:
http://forgeftp.novell.com//apparmor/LKML_Submission-May_07/techdoc.pdf

Under the restorecon-alike proposal, you have a HUGE open race. This
post http://bugs.centos.org/view.php?id=1981 describes restorecon
running for 30 minutes relabeling a file system. That is so far from
acceptable that it is silly.

Of course, this depends on the system in question, but restorecon will
necessarily need to traverse whatever portions of the filesystem that
have changed, which can be quite a long time indeed. Any race condition
measured in minutes is a very serious issue.

> I can't think of a "real world" use of moving directory trees around
> that this would come up in as a problem.
Consider this case: We've been developing a new web site for a month,
and testing it on the server by putting it in a different virtual
domain. We want to go live at some particular instant by doing an mv of
the content into our public HTML directory. We simultaneously want to
take the old web site down and archive it by moving it somewhere else.

Under the restorecon proposal, the web site would be horribly broken
until restorecon finishes, as various random pages are or are not
accessible to Apache.

In a smaller scale example, I want to share some files with a friend. I
can't be bothered to set up a proper access control system, so I just mv
the files to ~crispin/public_html/lookitme and in IRC say "get it now,
going away in 10 minutes" and then move it out again. Yes, you can
manually address this by running "restorecon ~crispin/public_html". But
AA does this automatically without having to run any commands.

You could get restorecon to do this automatically by using inotify. But
to make it as general and transparent as AA is now, you would have to
run inotify on every directory in the system, with consequences for
kernel memory and performance.

This problem does not exist for SELinux, because SELinux does not expect
access to change based on file names.

This problem does not exist in the proposed AA implementation, because
the patch makes the access decision based on the current name of the
file, so it doesn't have a consistency problem between the file and its
label; there is no label.

The problem is induced by trying to emulate AA on top of SELinux. They
don't fit well together. AA fits much better with LSM, which is the
reason LSM exists.

>   Maybe a source code control
> system might have this issue for the server, but in a second or two
> everything would be working again as the new files would be relabled
> correctly.
>   
Try an hour or two for a large source code repository. Its linear in the
number of files, and several hundred thousand files would take a while
to relabel. A large GIT tree would be particularly painful because of
the very large number of files.

> Can anyone else see a problem with this that I'm just being foolish and
> missing?
>   
It is not foolish. The label idea is so attractive that last September
from discussions with Arjan we actually thought it was the preferred
implementation. However, what we've been saying over and over again is
that we *tried* this, and it *doesn't* work at the implementation level.
There is no good answer, restorecon is an ugly kludge, and so this
seductive approach turns out to be a dead end.

Caveat: I am *not* saying that labels in general are bad, just that they
are a bad way to emulate the AppArmor model. And yes, I am working on a
model paper that is more abstract than Andreas' paper
<http://forgeftp.novell.com//apparmor/LKML_Submission-May_07/techdoc.pdf>,
but that takes time.

Then there's all the other problems, such as file systems that don't
support extended attributes, particularly NFS3. Yes, NFS3 is vulnerable
to network attack, but that is not the threat AA is addressing. AA is
preventing an application with access to an NFS mount from accessing the
*entire* mount. There is lots of practical security value in this, and
label schemes cannot do it. Well, mostly; you could do it with a dynamic
labeling scheme that labels files as they are pulled into kernel memory,
but that requires an AA-style regexp parser in the kernel to apply the
labels.

Crispin

-- 
Crispin Cowan, Ph.D.               http://crispincowan.com/~crispin/
Director of Software Engineering   http://novell.com
	AppArmor Chat: irc.oftc.net/#apparmor


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 20:06                 ` Pavel Machek
  2007-06-15 21:11                   ` Greg KH
@ 2007-06-15 23:33                   ` Seth Arnold
  2007-06-15 23:39                     ` Pavel Machek
  1 sibling, 1 reply; 240+ messages in thread
From: Seth Arnold @ 2007-06-15 23:33 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Greg KH, Crispin Cowan, Andreas Gruenbacher, Stephen Smalley,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 460 bytes --]

On Fri, Jun 15, 2007 at 10:06:23PM +0200, Pavel Machek wrote:
> Yes, you may get some -EPERM during the tree move, but AA has that
> problem already, see that "when madly moving trees we sometimes
> construct path file never ever had".

Pavel, please focus on the current AppArmor implementation. You're
remembering a flaw with a previous version of AppArmor. The pathnames
constructed with the current version of AppArmor are consistent and
correct.

Thanks.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 23:33                   ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Seth Arnold
@ 2007-06-15 23:39                     ` Pavel Machek
  2007-06-16  0:07                       ` Seth Arnold
  0 siblings, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-06-15 23:39 UTC (permalink / raw)
  To: Greg KH, Crispin Cowan, Andreas Gruenbacher, Stephen Smalley,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

Hi!

> > Yes, you may get some -EPERM during the tree move, but AA has that
> > problem already, see that "when madly moving trees we sometimes
> > construct path file never ever had".
> 
> Pavel, please focus on the current AppArmor implementation. You're
> remembering a flaw with a previous version of AppArmor. The pathnames
> constructed with the current version of AppArmor are consistent and
> correct.

Ok, I did not know that this got fixed.

How do you do that? Hold a lock preventing renames for a whole time
you walk from file to the root of filesystem?
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 23:30                     ` Crispin Cowan
@ 2007-06-15 23:49                       ` Greg KH
  2007-06-16  0:01                         ` david
                                           ` (3 more replies)
  2007-06-16  0:02                       ` Pavel Machek
  2007-06-16  0:48                       ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
  2 siblings, 4 replies; 240+ messages in thread
From: Greg KH @ 2007-06-15 23:49 UTC (permalink / raw)
  To: Crispin Cowan
  Cc: Pavel Machek, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Fri, Jun 15, 2007 at 04:30:44PM -0700, Crispin Cowan wrote:
> Greg KH wrote:
> > On Fri, Jun 15, 2007 at 10:06:23PM +0200, Pavel Machek wrote:
> >   
> >>>>     * Renamed Directory trees: The above problem is compounded with
> >>>>       directory trees. Changing the name at the top of a large, bushy
> >>>>       tree can require instant relabeling of millions of files.
> >>>>         
> >>> Same daemon can do this.  And yes, it might take a ammount of time, but
> >>> the times that this happens in "real-life" on a "production" server is
> >>> quite small, if at all.
> >>>       
> >> And now, if you move a tree, there will be old labels for a while. But
> >> this does not matter, because attacker could be keeping file
> >> descriptors.
> >>     
> > Agreed.
> >   
> We have built a label-based AA prototype. It fails because there is no
> reasonable way to address the tree renaming problem.

How does inotify not work here?  You are notified that the tree is
moved, your daemon goes through and relabels things as needed.  In the
meantime, before the re-label happens, you might have the wrong label on
things, but "somehow" SELinux already handles this, so I think you
should be fine.

> >> Only case where attacker _can't_ be keeping file descriptors is newly
> >> created files in recently moved tree. But as you already create files
> >> with restrictive permissions, that's okay.
> >>
> >> Yes, you may get some -EPERM during the tree move, but AA has that
> >> problem already, see that "when madly moving trees we sometimes
> >> construct path file never ever had".
> >>     
> > Exactly.
> >   
> You are remembering old behavior. The current AppArmor generates only
> correct and consistent paths. If a process has an open file descriptor
> to such a file, they will retain access to it, as we described here:
> http://forgeftp.novell.com//apparmor/LKML_Submission-May_07/techdoc.pdf
> 
> Under the restorecon-alike proposal, you have a HUGE open race. This
> post http://bugs.centos.org/view.php?id=1981 describes restorecon
> running for 30 minutes relabeling a file system. That is so far from
> acceptable that it is silly.

Ok, so we fix it.  Seriously, it shouldn't be that hard.  If that's the
only problem we have here, it isn't an issue.

> Of course, this depends on the system in question, but restorecon will
> necessarily need to traverse whatever portions of the filesystem that
> have changed, which can be quite a long time indeed. Any race condition
> measured in minutes is a very serious issue.

Agreed, so we fix that.  There are ways to speed those kinds of things
up quite a bit, and I imagine since the default SELinux behavior doesn't
use restorecon in this kind of use-case, no one has spent the time to do
the work.

> > I can't think of a "real world" use of moving directory trees around
> > that this would come up in as a problem.
> Consider this case: We've been developing a new web site for a month,
> and testing it on the server by putting it in a different virtual
> domain. We want to go live at some particular instant by doing an mv of
> the content into our public HTML directory. We simultaneously want to
> take the old web site down and archive it by moving it somewhere else.
> 
> Under the restorecon proposal, the web site would be horribly broken
> until restorecon finishes, as various random pages are or are not
> accessible to Apache.

Usually you don't do that by doing a 'mv' otherwise you are almost
guaranteed stale and mixed up content for some period of time, not to
mention the issues surrounding paths that might be messed up.

> In a smaller scale example, I want to share some files with a friend. I
> can't be bothered to set up a proper access control system, so I just mv
> the files to ~crispin/public_html/lookitme and in IRC say "get it now,
> going away in 10 minutes" and then move it out again. Yes, you can
> manually address this by running "restorecon ~crispin/public_html". But
> AA does this automatically without having to run any commands.

I'm saying that the daemon will automatically do it for you, you don't
have to do anything on your own.

> You could get restorecon to do this automatically by using inotify.

Yes.

> But to make it as general and transparent as AA is now, you would have
> to run inotify on every directory in the system, with consequences for
> kernel memory and performance.

What "kernel memory and performance" issues are there?  Your SLED
machine already has inotify running on every directory in the system
today, and you don't seem to have noticed that :)

> This problem does not exist for SELinux, because SELinux does not expect
> access to change based on file names.

Agreed.

> This problem does not exist in the proposed AA implementation, because
> the patch makes the access decision based on the current name of the
> file, so it doesn't have a consistency problem between the file and its
> label; there is no label.

No, that's not the issue here.  The issue is if we can use the model
that AA is exporting to users and apply it to the model that the kernel
uses internally to access internal data structures.

> The problem is induced by trying to emulate AA on top of SELinux. They
> don't fit well together. AA fits much better with LSM, which is the
> reason LSM exists.

Not really, LSM is there because originally people thought that a
general-purpose "hook" layer would be useful for implementing different
security models.  But for those types of models that do not map well to
internal kernel structures, perhaps they should be modeled on top of a
security system that does handle the internal kernel representation of
things in the way the kernel works.

> >   Maybe a source code control
> > system might have this issue for the server, but in a second or two
> > everything would be working again as the new files would be relabled
> > correctly.
> >   
> Try an hour or two for a large source code repository. Its linear in the
> number of files, and several hundred thousand files would take a while
> to relabel. A large GIT tree would be particularly painful because of
> the very large number of files.

No, git servers are only storing the sha files, not the "live" tree.
Well, if you want to waste space on your server you might have a copy of
the current tree, but that's a configuration problem on your system.

> > Can anyone else see a problem with this that I'm just being foolish and
> > missing?
> >   
> It is not foolish. The label idea is so attractive that last September
> from discussions with Arjan we actually thought it was the preferred
> implementation. However, what we've been saying over and over again is
> that we *tried* this, and it *doesn't* work at the implementation level.
> There is no good answer, restorecon is an ugly kludge, and so this
> seductive approach turns out to be a dead end.

Great, have any code I can look at?  It would be nice to start with an
already working implementation that is only slow instead of trying to
start from scratch.

> Then there's all the other problems, such as file systems that don't
> support extended attributes, particularly NFS3. Yes, NFS3 is vulnerable
> to network attack, but that is not the threat AA is addressing. AA is
> preventing an application with access to an NFS mount from accessing the
> *entire* mount. There is lots of practical security value in this, and
> label schemes cannot do it. Well, mostly; you could do it with a dynamic
> labeling scheme that labels files as they are pulled into kernel memory,
> but that requires an AA-style regexp parser in the kernel to apply the
> labels.

You still haven't answered Stephen's response to NFSv3, so until then,
please don't trot out this horse.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 21:42                     ` James Morris
@ 2007-06-15 23:50                       ` Greg KH
  2007-06-16  1:21                         ` James Morris
  0 siblings, 1 reply; 240+ messages in thread
From: Greg KH @ 2007-06-15 23:50 UTC (permalink / raw)
  To: James Morris
  Cc: Pavel Machek, Crispin Cowan, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, Jun 15, 2007 at 05:42:08PM -0400, James Morris wrote:
> On Fri, 15 Jun 2007, Greg KH wrote:
> 
> > > Or just create the files with restrictive labels by default. That way
> > > you "fail closed".
> > 
> > From my limited knowledge of SELinux, this is the default today so this
> > would happen by default.  Anyone with more SELinux experience want to
> > verify or fix my understanding of this?
> 
> This is entirely controllable via policy.  That is, you specify that newly 
> create files are labeled to something safe (enforced atomically at the 
> kernel level), and then your userland relabeler would be invoked via 
> inotify to relabel based on your userland pathname specification.
> 
> This labeling policy can be as granular as you wish, from the entire 
> filesystem to a single file.  It can also be applied depending on the 
> process which created the file and the directory its created in, ranging 
> from all processes and all directories, to say, just those running as 
> user_t in directories labeled as public_html_t (or whatever).

Oh great, then things like source code control systems would have no
problems with new files being created under them, or renaming whole
trees.

So, so much for the "it's going to be too slow re-labeling everything"
issue, as it's not even required for almost all situations :)

thanks for letting us know.

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 23:49                       ` Greg KH
@ 2007-06-16  0:01                         ` david
  2007-06-16  0:20                           ` Pavel Machek
                                             ` (2 more replies)
  2007-06-16  0:18                         ` Seth Arnold
                                           ` (2 subsequent siblings)
  3 siblings, 3 replies; 240+ messages in thread
From: david @ 2007-06-16  0:01 UTC (permalink / raw)
  To: Greg KH
  Cc: Crispin Cowan, Pavel Machek, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, 15 Jun 2007, Greg KH wrote:

> On Fri, Jun 15, 2007 at 04:30:44PM -0700, Crispin Cowan wrote:
>> Greg KH wrote:
>>> On Fri, Jun 15, 2007 at 10:06:23PM +0200, Pavel Machek wrote:
>>>> Only case where attacker _can't_ be keeping file descriptors is newly
>>>> created files in recently moved tree. But as you already create files
>>>> with restrictive permissions, that's okay.
>>>>
>>>> Yes, you may get some -EPERM during the tree move, but AA has that
>>>> problem already, see that "when madly moving trees we sometimes
>>>> construct path file never ever had".
>>>>
>>> Exactly.
>>>
>> You are remembering old behavior. The current AppArmor generates only
>> correct and consistent paths. If a process has an open file descriptor
>> to such a file, they will retain access to it, as we described here:
>> http://forgeftp.novell.com//apparmor/LKML_Submission-May_07/techdoc.pdf
>>
>> Under the restorecon-alike proposal, you have a HUGE open race. This
>> post http://bugs.centos.org/view.php?id=1981 describes restorecon
>> running for 30 minutes relabeling a file system. That is so far from
>> acceptable that it is silly.
>
> Ok, so we fix it.  Seriously, it shouldn't be that hard.  If that's the
> only problem we have here, it isn't an issue.

how do you 'fix' the laws of physics?

the problem is that with a directory that contains lots of files below it 
you have to access all the files metadata to change the labels on it. it 
can take significant amounts of time to walk the entire three and change 
every file.

>>> I can't think of a "real world" use of moving directory trees around
>>> that this would come up in as a problem.
>> Consider this case: We've been developing a new web site for a month,
>> and testing it on the server by putting it in a different virtual
>> domain. We want to go live at some particular instant by doing an mv of
>> the content into our public HTML directory. We simultaneously want to
>> take the old web site down and archive it by moving it somewhere else.
>>
>> Under the restorecon proposal, the web site would be horribly broken
>> until restorecon finishes, as various random pages are or are not
>> accessible to Apache.
>
> Usually you don't do that by doing a 'mv' otherwise you are almost
> guaranteed stale and mixed up content for some period of time, not to
> mention the issues surrounding paths that might be messed up.

on the contrary, useing 'mv' is by far the cleanest way to do this.

mv htdocs htdocs.old;mv htdocs.new htdocs

this makes two atomic changes to the filesystem, but can generate 
thousands to millions of permission changes as a result.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 23:30                     ` Crispin Cowan
  2007-06-15 23:49                       ` Greg KH
@ 2007-06-16  0:02                       ` Pavel Machek
  2007-06-21 16:08                         ` Lars Marowsky-Bree
  2007-06-16  0:48                       ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
  2 siblings, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-06-16  0:02 UTC (permalink / raw)
  To: Crispin Cowan
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

Hi!

> >> Only case where attacker _can't_ be keeping file descriptors is newly
> >> created files in recently moved tree. But as you already create files
> >> with restrictive permissions, that's okay.
> >>
> >> Yes, you may get some -EPERM during the tree move, but AA has that
> >> problem already, see that "when madly moving trees we sometimes
> >> construct path file never ever had".
> >>     
> > Exactly.
> >   
> You are remembering old behavior. The current AppArmor generates only
> correct and consistent paths. If a process has an open file descriptor
> to such a file, they will retain access to it, as we described here:

Ok, so what I described was actually secure. Good.

> Under the restorecon-alike proposal, you have a HUGE open race. This
> post http://bugs.centos.org/view.php?id=1981 describes restorecon
> running for 30 minutes relabeling a file system. That is so far from
> acceptable that it is silly.

30 minutes during installation does not seem "silly" to me.

And that race does not make it insecure, because of the open file
descriptors. Good.

> Of course, this depends on the system in question, but restorecon will
> necessarily need to traverse whatever portions of the filesystem that
> have changed, which can be quite a long time indeed. Any race condition
> measured in minutes is a very serious issue.

You seem to imply it is security related, it is not. I can have open
files for hours or days.

> > I can't think of a "real world" use of moving directory trees around
> > that this would come up in as a problem.
> Consider this case: We've been developing a new web site for a month,
> and testing it on the server by putting it in a different virtual
> domain. We want to go live at some particular instant by doing an mv of
> the content into our public HTML directory. We simultaneously want to
> take the old web site down and archive it by moving it somewhere
> else.

And you do that exactly how, without the race? I do not think ve have
three_way_rename(name1, name2, name3) system call.

Notice that

1) mv can take minutes already if you move cross filesystem.

2) this is easily avoided by mv-ing somewhere with "same" permissons,
then doing quick moves when daemon is done.

> You could get restorecon to do this automatically by using inotify. But
> to make it as general and transparent as AA is now, you would have to
> run inotify on every directory in the system, with consequences for
> kernel memory and performance.

So you run inotify everywhere. IIRC beagle does it already.

> > Can anyone else see a problem with this that I'm just being foolish and
> > missing?
> >   
> It is not foolish. The label idea is so attractive that last September
> from discussions with Arjan we actually thought it was the preferred
> implementation. However, what we've been saying over and over again is
> that we *tried* this, and it *doesn't* work at the implementation level.
> There is no good answer, restorecon is an ugly kludge, and so this
> seductive approach turns out to be a dead end.

Talking about dead ends... "just put path-based security module into
kernel" recently got pretty strong "NACK" from Christoph Hellwig (see
TOMOYO Linux thread), and I believe there was similar comment from Al
Viro in past. That seems to me as dead-endy as it gets. "mv takes 30
minutes" is road slightly covered with bushes... compared to that.

So we can either forget about AA completely, or take a way Christoph
did not "NACK". restorecond is such a way, and with inotify it should
be acceptable. find does _not_ take that long, not even for git trees.

pavel@amd:/data/l/linux$ time find . > /dev/null
0.04user 0.37system 11.50 (0m11.504s) elapsed 3.56%CPU

(If you wanted to be super-nice, you could introduce rename() helper
into glibc, that would do re-labeling synchronously, and only return
when it is done. All the nice applications call glibc anyway, and all
the exploits can't take advantage of it, because it is secure
already.).

								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 23:39                     ` Pavel Machek
@ 2007-06-16  0:07                       ` Seth Arnold
  0 siblings, 0 replies; 240+ messages in thread
From: Seth Arnold @ 2007-06-16  0:07 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Greg KH, Crispin Cowan, Andreas Gruenbacher, Stephen Smalley,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 584 bytes --]

On Sat, Jun 16, 2007 at 01:39:14AM +0200, Pavel Machek wrote:
> > Pavel, please focus on the current AppArmor implementation. You're
> > remembering a flaw with a previous version of AppArmor. The pathnames
> > constructed with the current version of AppArmor are consistent and
> > correct.
> 
> Ok, I did not know that this got fixed.
> 
> How do you do that? Hold a lock preventing renames for a whole time
> you walk from file to the root of filesystem?

We've improved d_path() to remove many of its previous shortcomings:

eb3dfb0cb1f4a44e2d0553f89514ce9f2a9fcaf1

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 23:49                       ` Greg KH
  2007-06-16  0:01                         ` david
@ 2007-06-16  0:18                         ` Seth Arnold
  2007-06-16  0:29                           ` Greg KH
                                             ` (2 more replies)
  2007-06-18 18:48                         ` Crispin Cowan
  2007-06-21 16:01                         ` Andreas Gruenbacher
  3 siblings, 3 replies; 240+ messages in thread
From: Seth Arnold @ 2007-06-16  0:18 UTC (permalink / raw)
  To: Greg KH
  Cc: Crispin Cowan, Pavel Machek, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 2403 bytes --]

On Fri, Jun 15, 2007 at 04:49:25PM -0700, Greg KH wrote:
> > We have built a label-based AA prototype. It fails because there is no
> > reasonable way to address the tree renaming problem.
> 
> How does inotify not work here?  You are notified that the tree is
> moved, your daemon goes through and relabels things as needed.  In the
> meantime, before the re-label happens, you might have the wrong label on
> things, but "somehow" SELinux already handles this, so I think you
> should be fine.

SELinux does not relabel files when containing directories move, so it
is not a problem they've chosen to face.

How well does inotify handle running attached to every directory on a
typical Linux system?

> > Under the restorecon-alike proposal, you have a HUGE open race. This
> > post http://bugs.centos.org/view.php?id=1981 describes restorecon
> > running for 30 minutes relabeling a file system. That is so far from
> > acceptable that it is silly.
> 
> Ok, so we fix it.  Seriously, it shouldn't be that hard.  If that's the
> only problem we have here, it isn't an issue.

Restorecon traverses the filesystem from a specific down. In order to
apply to an entire system (as would be necessary to try to emulate
AppArmor's model using SELinux), restorecon would need to run on vast
portions of the filesystem often. (mv ~/public_html ~/archived; or tar
zxvf linux-*.tar.gz, etc.)

I'm not sure we need to run restorecon every time rename(2) is called.

> > Of course, this depends on the system in question, but restorecon will
> > necessarily need to traverse whatever portions of the filesystem that
> > have changed, which can be quite a long time indeed. Any race condition
> > measured in minutes is a very serious issue.
> 
> Agreed, so we fix that.  There are ways to speed those kinds of things
> up quite a bit, and I imagine since the default SELinux behavior doesn't
> use restorecon in this kind of use-case, no one has spent the time to do
> the work.

The time for restorecon is probably best imagined as a kind of 'du' that
also updates extended attributes as it does its work. It'd be very
difficult to improve on this.

> What "kernel memory and performance" issues are there?  Your SLED
> machine already has inotify running on every directory in the system
> today, and you don't seem to have noticed that :)

I beg to differ. :)

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  0:01                         ` david
@ 2007-06-16  0:20                           ` Pavel Machek
  2007-06-22  9:59                             ` Andreas Gruenbacher
  2007-06-16  0:31                           ` Greg KH
  2007-06-16  1:41                           ` James Morris
  2 siblings, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-06-16  0:20 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Crispin Cowan, Andreas Gruenbacher, Stephen Smalley,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

Hi!

> >>Under the restorecon proposal, the web site would be horribly broken
> >>until restorecon finishes, as various random pages are or are not
> >>accessible to Apache.
> >
> >Usually you don't do that by doing a 'mv' otherwise you are almost
> >guaranteed stale and mixed up content for some period of time, not to
> >mention the issues surrounding paths that might be messed up.
> 
> on the contrary, useing 'mv' is by far the cleanest way to do this.
> 
> mv htdocs htdocs.old;mv htdocs.new htdocs
> 
> this makes two atomic changes to the filesystem, but can generate 
> thousands to millions of permission changes as a result.

Ok, so mv gets slower for big trees... and open() gets faster for deep
trees. Previously, open in current directory was one atomic read of
directory entry, now it has to read directory, and its parent, and its
parent parent, and its...

(Or am I wrong and getting full path does not need to bring anything
in, not even in cache-cold case?)

So, proposed solution has different performance tradeoffs, but should
still be a win -- opens are more common than moves.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  0:18                         ` Seth Arnold
@ 2007-06-16  0:29                           ` Greg KH
  2007-06-16  1:46                           ` James Morris
  2007-06-16  2:19                           ` James Morris
  2 siblings, 0 replies; 240+ messages in thread
From: Greg KH @ 2007-06-16  0:29 UTC (permalink / raw)
  To: Crispin Cowan, Pavel Machek, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, Jun 15, 2007 at 05:18:10PM -0700, Seth Arnold wrote:
> On Fri, Jun 15, 2007 at 04:49:25PM -0700, Greg KH wrote:
> > > We have built a label-based AA prototype. It fails because there is no
> > > reasonable way to address the tree renaming problem.
> > 
> > How does inotify not work here?  You are notified that the tree is
> > moved, your daemon goes through and relabels things as needed.  In the
> > meantime, before the re-label happens, you might have the wrong label on
> > things, but "somehow" SELinux already handles this, so I think you
> > should be fine.
> 
> SELinux does not relabel files when containing directories move, so it
> is not a problem they've chosen to face.
> 
> How well does inotify handle running attached to every directory on a
> typical Linux system?

Look at SLED and Beagle (taking the indexing logic out of the equation.)
It runs good enough that a major Linux vendor is willing to stake its
reputation on it :)

> > > Under the restorecon-alike proposal, you have a HUGE open race. This
> > > post http://bugs.centos.org/view.php?id=1981 describes restorecon
> > > running for 30 minutes relabeling a file system. That is so far from
> > > acceptable that it is silly.
> > 
> > Ok, so we fix it.  Seriously, it shouldn't be that hard.  If that's the
> > only problem we have here, it isn't an issue.
> 
> Restorecon traverses the filesystem from a specific down. In order to
> apply to an entire system (as would be necessary to try to emulate
> AppArmor's model using SELinux), restorecon would need to run on vast
> portions of the filesystem often. (mv ~/public_html ~/archived; or tar
> zxvf linux-*.tar.gz, etc.)
> 
> I'm not sure we need to run restorecon every time rename(2) is called.

Ok, so we optimize it.  Putting speed issues aside right now as a "mere"
implementation details, I'm looking for logical reasons the AA model
will not work in this type of system.

> > > Of course, this depends on the system in question, but restorecon will
> > > necessarily need to traverse whatever portions of the filesystem that
> > > have changed, which can be quite a long time indeed. Any race condition
> > > measured in minutes is a very serious issue.
> > 
> > Agreed, so we fix that.  There are ways to speed those kinds of things
> > up quite a bit, and I imagine since the default SELinux behavior doesn't
> > use restorecon in this kind of use-case, no one has spent the time to do
> > the work.
> 
> The time for restorecon is probably best imagined as a kind of 'du' that
> also updates extended attributes as it does its work. It'd be very
> difficult to improve on this.

Is that a bet?  :)

> > What "kernel memory and performance" issues are there?  Your SLED
> > machine already has inotify running on every directory in the system
> > today, and you don't seem to have noticed that :)
> 
> I beg to differ. :)

The Beagle index backend is known to slow things down at times, yes, but
is that the fault of the inotify watches, or the use of mono and a
big-ass database on the system at the same time?

In the original inotify development, the issue was not inotify at all,
unless you have some newer numbers in this regard?

And Crispin mentioned that you all already implemented this.  Do you
have the code around so that we can take a look at it?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  0:01                         ` david
  2007-06-16  0:20                           ` Pavel Machek
@ 2007-06-16  0:31                           ` Greg KH
  2007-06-16  8:09                             ` david
  2007-06-16  1:41                           ` James Morris
  2 siblings, 1 reply; 240+ messages in thread
From: Greg KH @ 2007-06-16  0:31 UTC (permalink / raw)
  To: david
  Cc: Crispin Cowan, Pavel Machek, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, Jun 15, 2007 at 05:01:25PM -0700, david@lang.hm wrote:
>  On Fri, 15 Jun 2007, Greg KH wrote:
> 
> > On Fri, Jun 15, 2007 at 04:30:44PM -0700, Crispin Cowan wrote:
> >> Greg KH wrote:
> >>> On Fri, Jun 15, 2007 at 10:06:23PM +0200, Pavel Machek wrote:
> >>>> Only case where attacker _can't_ be keeping file descriptors is newly
> >>>> created files in recently moved tree. But as you already create files
> >>>> with restrictive permissions, that's okay.
> >>>>
> >>>> Yes, you may get some -EPERM during the tree move, but AA has that
> >>>> problem already, see that "when madly moving trees we sometimes
> >>>> construct path file never ever had".
> >>>>
> >>> Exactly.
> >>>
> >> You are remembering old behavior. The current AppArmor generates only
> >> correct and consistent paths. If a process has an open file descriptor
> >> to such a file, they will retain access to it, as we described here:
> >> http://forgeftp.novell.com//apparmor/LKML_Submission-May_07/techdoc.pdf
> >>
> >> Under the restorecon-alike proposal, you have a HUGE open race. This
> >> post http://bugs.centos.org/view.php?id=1981 describes restorecon
> >> running for 30 minutes relabeling a file system. That is so far from
> >> acceptable that it is silly.
> >
> > Ok, so we fix it.  Seriously, it shouldn't be that hard.  If that's the
> > only problem we have here, it isn't an issue.
> 
>  how do you 'fix' the laws of physics?
> 
>  the problem is that with a directory that contains lots of files below it 
>  you have to access all the files metadata to change the labels on it. it can 
>  take significant amounts of time to walk the entire three and change every 
>  file.

Agreed, but you can do this in ways that are faster than others :)

> >>> I can't think of a "real world" use of moving directory trees around
> >>> that this would come up in as a problem.
> >> Consider this case: We've been developing a new web site for a month,
> >> and testing it on the server by putting it in a different virtual
> >> domain. We want to go live at some particular instant by doing an mv of
> >> the content into our public HTML directory. We simultaneously want to
> >> take the old web site down and archive it by moving it somewhere else.
> >>
> >> Under the restorecon proposal, the web site would be horribly broken
> >> until restorecon finishes, as various random pages are or are not
> >> accessible to Apache.
> >
> > Usually you don't do that by doing a 'mv' otherwise you are almost
> > guaranteed stale and mixed up content for some period of time, not to
> > mention the issues surrounding paths that might be messed up.
> 
>  on the contrary, useing 'mv' is by far the cleanest way to do this.
> 
>  mv htdocs htdocs.old;mv htdocs.new htdocs
> 
>  this makes two atomic changes to the filesystem, but can generate thousands 
>  to millions of permission changes as a result.

I agree, and yet, somehow, SELinux today handles this just fine, right?
:)

Let's worry about speed issues later on when a working implementation is
produced, I'm still looking for the logical reason a system like this
can not work properly based on the expected AA interface to users.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-15 23:30                     ` Crispin Cowan
  2007-06-15 23:49                       ` Greg KH
  2007-06-16  0:02                       ` Pavel Machek
@ 2007-06-16  0:48                       ` Tetsuo Handa
  2007-06-19 15:25                         ` Pavel Machek
  2 siblings, 1 reply; 240+ messages in thread
From: Tetsuo Handa @ 2007-06-16  0:48 UTC (permalink / raw)
  To: crispin; +Cc: linux-kernel, linux-security-module

Crispin Cowan wrote:
> In a smaller scale example, I want to share some files with a friend. I
> can't be bothered to set up a proper access control system, so I just mv
> the files to ~crispin/public_html/lookitme and in IRC say "get it now,
> going away in 10 minutes" and then move it out again. Yes, you can
> manually address this by running "restorecon ~crispin/public_html". But
> AA does this automatically without having to run any commands.
If you share ~crispin/public_html/lookitme by making a hard link,
does relabeling approach work?
I thought SELinux allows only one label for one file.
If AA (on the top of SELinux) tries to allow different permissions to
~crispin/public_html/lookitme and its original location,
either one of two pathnames won't be accessible as intended, will it?

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 23:50                       ` Greg KH
@ 2007-06-16  1:21                         ` James Morris
  2007-06-16  2:57                           ` Casey Schaufler
  2007-06-16  4:23                           ` Greg KH
  0 siblings, 2 replies; 240+ messages in thread
From: James Morris @ 2007-06-16  1:21 UTC (permalink / raw)
  To: Greg KH
  Cc: Pavel Machek, Crispin Cowan, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, 15 Jun 2007, Greg KH wrote:

> Oh great, then things like source code control systems would have no
> problems with new files being created under them, or renaming whole
> trees.

It depends -- I think we may be talking about different things.

If you're using inotify to watch for new files and kick something in 
userspace to relabel them, it could take a while to relabel a lot of 
files, although there are likely some gains to be had from parallel 
relabeling which we've not explored.

What I was saying is that you can use traditional SELinux labeling policy 
underneath that to ensure that there is always a safe label on each file 
before it is relabeled from userspace.

> So, so much for the "it's going to be too slow re-labeling everything"
> issue, as it's not even required for almost all situations :)

You could probably get an idea of the cost by running something like:

$ time find /usr/src/linux | xargs setfattr -n user.foo -v bar

On my system, it takes about 1.2 seconds to label a fully checked out 
kernel source tree with ~23,000 files in this manner, on a stock standard 
ext3 filesystem with a SATA drive.



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  0:01                         ` david
  2007-06-16  0:20                           ` Pavel Machek
  2007-06-16  0:31                           ` Greg KH
@ 2007-06-16  1:41                           ` James Morris
  2 siblings, 0 replies; 240+ messages in thread
From: James Morris @ 2007-06-16  1:41 UTC (permalink / raw)
  To: david
  Cc: Greg KH, Crispin Cowan, Pavel Machek, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, 15 Jun 2007, david@lang.hm wrote:

> on the contrary, useing 'mv' is by far the cleanest way to do this.
> 
> mv htdocs htdocs.old;mv htdocs.new htdocs
> 
> this makes two atomic changes to the filesystem, but can generate thousands to
> millions of permission changes as a result.

OTOH, you've performed your labeling up front, and don't have to 
effectively relabel each file each time on each access, which is what 
you're really doing with pathname labeling.



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  0:18                         ` Seth Arnold
  2007-06-16  0:29                           ` Greg KH
@ 2007-06-16  1:46                           ` James Morris
  2007-06-16  2:19                           ` James Morris
  2 siblings, 0 replies; 240+ messages in thread
From: James Morris @ 2007-06-16  1:46 UTC (permalink / raw)
  To: Seth Arnold
  Cc: Greg KH, Crispin Cowan, Pavel Machek, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, 15 Jun 2007, Seth Arnold wrote:

> > How does inotify not work here?  You are notified that the tree is
> > moved, your daemon goes through and relabels things as needed.  In the
> > meantime, before the re-label happens, you might have the wrong label on
> > things, but "somehow" SELinux already handles this, so I think you
> > should be fine.
> 
> SELinux does not relabel files when containing directories move, so it
> is not a problem they've chosen to face.

It's a deliberate design choice, and follows traditional Unix security 
logic.  DAC permissions don't change on every file in the subtree when you 
mv directories, either.




- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  0:18                         ` Seth Arnold
  2007-06-16  0:29                           ` Greg KH
  2007-06-16  1:46                           ` James Morris
@ 2007-06-16  2:19                           ` James Morris
  2 siblings, 0 replies; 240+ messages in thread
From: James Morris @ 2007-06-16  2:19 UTC (permalink / raw)
  To: Seth Arnold
  Cc: Greg KH, Crispin Cowan, Pavel Machek, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, 15 Jun 2007, Seth Arnold wrote:

> The time for restorecon is probably best imagined as a kind of 'du' that
> also updates extended attributes as it does its work. It'd be very
> difficult to improve on this.

restorecon can most definitely be improved. 


- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  1:21                         ` James Morris
@ 2007-06-16  2:57                           ` Casey Schaufler
  2007-06-16  3:39                             ` James Morris
  2007-06-16  4:23                           ` Greg KH
  1 sibling, 1 reply; 240+ messages in thread
From: Casey Schaufler @ 2007-06-16  2:57 UTC (permalink / raw)
  To: James Morris, Greg KH
  Cc: Pavel Machek, Crispin Cowan, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel


--- James Morris <jmorris@namei.org> wrote:

> On my system, it takes about 1.2 seconds to label a fully checked out 
> kernel source tree with ~23,000 files in this manner

That's an eternity for that many files to be improperly labeled.
If, and the "if" didn't originate with me, your policy is
demonstrably correct (how do you do that?) for all domains
you could claim that the action is safe, if not ideal. 
I can't say if an evaluation team would buy the "safe"
argument. They've been known to balk before.


Casey Schaufler
casey@schaufler-ca.com

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  2:57                           ` Casey Schaufler
@ 2007-06-16  3:39                             ` James Morris
  2007-06-18  1:51                               ` Casey Schaufler
  0 siblings, 1 reply; 240+ messages in thread
From: James Morris @ 2007-06-16  3:39 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Greg KH, Pavel Machek, Crispin Cowan, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, 15 Jun 2007, Casey Schaufler wrote:

> 
> --- James Morris <jmorris@namei.org> wrote:
> 
> > On my system, it takes about 1.2 seconds to label a fully checked out 
> > kernel source tree with ~23,000 files in this manner
> 
> That's an eternity for that many files to be improperly labeled.
> If, and the "if" didn't originate with me, your policy is
> demonstrably correct (how do you do that?) for all domains
> you could claim that the action is safe, if not ideal. 
> I can't say if an evaluation team would buy the "safe"
> argument. They've been known to balk before.

To clarify:

We are discussing a scheme where the underlying SELinux labeling policy 
always ensures a safe label on a file, and then relabeling newly created 
files according to their pathnames.

There is no expectation that this scheme would be submitted for 
certification.  Its purpose is to merely to provide pathname-based 
labeling outside of the kernel.



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  1:21                         ` James Morris
  2007-06-16  2:57                           ` Casey Schaufler
@ 2007-06-16  4:23                           ` Greg KH
  1 sibling, 0 replies; 240+ messages in thread
From: Greg KH @ 2007-06-16  4:23 UTC (permalink / raw)
  To: James Morris
  Cc: Pavel Machek, Crispin Cowan, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, Jun 15, 2007 at 09:21:57PM -0400, James Morris wrote:
> On Fri, 15 Jun 2007, Greg KH wrote:
> 
> > Oh great, then things like source code control systems would have no
> > problems with new files being created under them, or renaming whole
> > trees.
> 
> It depends -- I think we may be talking about different things.
> 
> If you're using inotify to watch for new files and kick something in 
> userspace to relabel them, it could take a while to relabel a lot of 
> files, although there are likely some gains to be had from parallel 
> relabeling which we've not explored.
> 
> What I was saying is that you can use traditional SELinux labeling policy 
> underneath that to ensure that there is always a safe label on each file 
> before it is relabeled from userspace.

Ok, yes, I think we are in violent agreement here :)

> > So, so much for the "it's going to be too slow re-labeling everything"
> > issue, as it's not even required for almost all situations :)
> 
> You could probably get an idea of the cost by running something like:
> 
> $ time find /usr/src/linux | xargs setfattr -n user.foo -v bar
> 
> On my system, it takes about 1.2 seconds to label a fully checked out 
> kernel source tree with ~23,000 files in this manner, on a stock standard 
> ext3 filesystem with a SATA drive.

Yeah, that should be very reasonable.  I'll wait to see Crispin's code
to work off of and see if I can get it to approach that kind of speed.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  0:31                           ` Greg KH
@ 2007-06-16  8:09                             ` david
  2007-06-16 16:24                               ` Greg KH
  0 siblings, 1 reply; 240+ messages in thread
From: david @ 2007-06-16  8:09 UTC (permalink / raw)
  To: Greg KH
  Cc: Crispin Cowan, Pavel Machek, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, 15 Jun 2007, Greg KH wrote:

>>> Usually you don't do that by doing a 'mv' otherwise you are almost
>>> guaranteed stale and mixed up content for some period of time, not to
>>> mention the issues surrounding paths that might be messed up.
>>
>>  on the contrary, useing 'mv' is by far the cleanest way to do this.
>>
>>  mv htdocs htdocs.old;mv htdocs.new htdocs
>>
>>  this makes two atomic changes to the filesystem, but can generate thousands
>>  to millions of permission changes as a result.
>
> I agree, and yet, somehow, SELinux today handles this just fine, right?
> :)

no it doesn't, SELinux as-is should take no action when the above command 
is run, but SELinux implementing path-based permissions will have to 
relabel every file or directory in both trees.

> Let's worry about speed issues later on when a working implementation is
> produced, I'm still looking for the logical reason a system like this
> can not work properly based on the expected AA interface to users.

if you are willing to live with the race conditions from the slow 
(re)labeling and write the software to scan the entire system to figure 
out the right policies (and then use inotify to watch the entire system 
for changes and (re)label the appropriate files) and accept that you can't 
get any granular security for filesystems that don't nativly support it 
you could make SELinux behave like AA.

but why should they be required to? are you saying that the LSM hooks are 
not a valid API and should be removed with all future security modules 
being based on SELinux?

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-15 16:50               ` Greg KH
  2007-06-15 18:01                 ` Casey Schaufler
  2007-06-15 20:06                 ` Pavel Machek
@ 2007-06-16 15:44                 ` Tetsuo Handa
  2007-06-16 16:26                   ` Greg KH
  2 siblings, 1 reply; 240+ messages in thread
From: Tetsuo Handa @ 2007-06-16 15:44 UTC (permalink / raw)
  To: greg; +Cc: linux-kernel, linux-security-module

Greg KH wrote:
> A daemon using inotify can "instantly"[1] detect this and label the file
> properly if it shows up.

> Same daemon can do the re-label.

Can the daemon using inotify access to all pathnames in all process's namespaces?
Are the namespace the daemon has and the namespace of pathnames notified via inotify always the same?

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  8:09                             ` david
@ 2007-06-16 16:24                               ` Greg KH
  0 siblings, 0 replies; 240+ messages in thread
From: Greg KH @ 2007-06-16 16:24 UTC (permalink / raw)
  To: david
  Cc: Crispin Cowan, Pavel Machek, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Sat, Jun 16, 2007 at 01:09:06AM -0700, david@lang.hm wrote:
>  On Fri, 15 Jun 2007, Greg KH wrote:
> 
> >>> Usually you don't do that by doing a 'mv' otherwise you are almost
> >>> guaranteed stale and mixed up content for some period of time, not to
> >>> mention the issues surrounding paths that might be messed up.
> >>
> >>  on the contrary, useing 'mv' is by far the cleanest way to do this.
> >>
> >>  mv htdocs htdocs.old;mv htdocs.new htdocs
> >>
> >>  this makes two atomic changes to the filesystem, but can generate 
> >> thousands
> >>  to millions of permission changes as a result.
> >
> > I agree, and yet, somehow, SELinux today handles this just fine, right?
> > :)
> 
>  no it doesn't, SELinux as-is should take no action when the above command is 
>  run, but SELinux implementing path-based permissions will have to relabel 
>  every file or directory in both trees.

Agreed.

> > Let's worry about speed issues later on when a working implementation is
> > produced, I'm still looking for the logical reason a system like this
> > can not work properly based on the expected AA interface to users.
> 
>  if you are willing to live with the race conditions from the slow 
>  (re)labeling and write the software to scan the entire system to figure out 
>  the right policies (and then use inotify to watch the entire system for 
>  changes and (re)label the appropriate files) and accept that you can't get 
>  any granular security for filesystems that don't nativly support it you 
>  could make SELinux behave like AA.

You make it sound like such a pretty picture :)

Anyway, I don't think there are "race conditions", just a bit of a delay
at times for situations that are not common or "normal operations".  And
as I think the speed issues can be drasticly reduced, I don't think
that's a really big deal just yet.  I'm trying to determine if there's
any logical reason why we can't do this and have yet to see proof of
that.

>  but why should they be required to? are you saying that the LSM hooks are 
>  not a valid API and should be removed with all future security modules being 
>  based on SELinux?

Woah, that's a huge logical jump that I am not willing to make at this
point in time.

The reason I am proposing this for AA is due to the impeadance between
the AA model and how the kernel internally works.  A number of core
kernel  VFS developers have objected to the AA code and changes because
of this problem and me and Pavel are here working to try to resolve this
in a way that is acceptable to everyone involved (kernel developers and
AA developers and AA end users.)

I'll leave the whole "LSM should be just replaced with SELinux"
discussion for later, as it is not relevant to this current topic at
all.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-16 15:44                 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
@ 2007-06-16 16:26                   ` Greg KH
  2007-06-16 16:45                     ` [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching Tetsuo Handa
  0 siblings, 1 reply; 240+ messages in thread
From: Greg KH @ 2007-06-16 16:26 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: linux-kernel, linux-security-module

On Sun, Jun 17, 2007 at 12:44:08AM +0900, Tetsuo Handa wrote:
> Greg KH wrote:
> > A daemon using inotify can "instantly"[1] detect this and label the file
> > properly if it shows up.
> 
> > Same daemon can do the re-label.
> 
> Can the daemon using inotify access to all pathnames in all process's
> namespaces?

I don't see why not, do you?

> Are the namespace the daemon has and the namespace of pathnames
> notified via inotify always the same?

If they are in the same namespace, then yes, they will as far as I can
tell.  Do you think this is incorrect?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching
  2007-06-16 16:26                   ` Greg KH
@ 2007-06-16 16:45                     ` Tetsuo Handa
  0 siblings, 0 replies; 240+ messages in thread
From: Tetsuo Handa @ 2007-06-16 16:45 UTC (permalink / raw)
  To: greg; +Cc: linux-kernel, linux-security-module


Greg KH wrote:
> On Sun, Jun 17, 2007 at 12:44:08AM +0900, Tetsuo Handa wrote:
> > Can the daemon using inotify access to all pathnames in all process's
> > namespaces?
> 
> I don't see why not, do you?
> 
> > Are the namespace the daemon has and the namespace of pathnames
> > notified via inotify always the same?
> 
> If they are in the same namespace, then yes, they will as far as I can
> tell.  Do you think this is incorrect?

At least, I think SELinux's "make relabel" can't relabel
files that are not in the namespace of "make" process.

I don't know how to use inotify, but what I worried is ...

If there are cases they are in different namespace,
it is impossible to relabel using userland daemon
(i.e. deferred-relabeling won't work)
unless all pathnames of all namespaces are somehow
accessible via inotify.

Thanks.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  3:39                             ` James Morris
@ 2007-06-18  1:51                               ` Casey Schaufler
  2007-06-18 11:29                                 ` Joshua Brindle
  0 siblings, 1 reply; 240+ messages in thread
From: Casey Schaufler @ 2007-06-18  1:51 UTC (permalink / raw)
  To: James Morris, Casey Schaufler
  Cc: Greg KH, Pavel Machek, Crispin Cowan, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel


--- James Morris <jmorris@namei.org> wrote:

> On Fri, 15 Jun 2007, Casey Schaufler wrote:
> 
> > 
> > --- James Morris <jmorris@namei.org> wrote:
> > 
> > > On my system, it takes about 1.2 seconds to label a fully checked out 
> > > kernel source tree with ~23,000 files in this manner
> > 
> > That's an eternity for that many files to be improperly labeled.
> > If, and the "if" didn't originate with me, your policy is
> > demonstrably correct (how do you do that?) for all domains
> > you could claim that the action is safe, if not ideal. 
> > I can't say if an evaluation team would buy the "safe"
> > argument. They've been known to balk before.
> 
> To clarify:
> 
> We are discussing a scheme where the underlying SELinux labeling policy 
> always ensures a safe label on a file, and then relabeling newly created 
> files according to their pathnames.

To counter clarify:

You are saying two things:
1. The policy always ensures a safe label.
2. Files can be relabeled in a reasonable and timely manner.

I have no questions about 2. It's a hack, but you've already
acknowledged that and it will work, allowing for some potential
cases where someone is overeager about getting a file-in-transition.

Regarding 1: This is a founding premise of the arguement, that
the "policy" is written correctly such that there is no case
where a file gets created with an unsafe label. Given the external
nature of the policy, and the number of attributes used within
the policy, and the overall sophistication of the policy mechanism,
how does one ...

    a. know that a label is "safe"
    b. know that a file will get a "safe" label
    c. know that the policy is "correctly" written as required

The question is not if fixxerupperd can set things right.
The question is about the properly written policy that is
required to make the mechanism worth discussing.

> There is no expectation that this scheme would be submitted for 
> certification.

De-nial.

> Its purpose is to merely to provide pathname-based 
> labeling outside of the kernel.

If you already have an in-kernel labeling scheme that you
trust to make the world safe until you get around to doing
the labeling externally you can argue that it's good enough.
But, to quote Cinderella's Stepmother, "I said "if"".


Casey Schaufler
casey@schaufler-ca.com

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-18  1:51                               ` Casey Schaufler
@ 2007-06-18 11:29                                 ` Joshua Brindle
  0 siblings, 0 replies; 240+ messages in thread
From: Joshua Brindle @ 2007-06-18 11:29 UTC (permalink / raw)
  To: casey
  Cc: James Morris, Greg KH, Pavel Machek, Crispin Cowan,
	Andreas Gruenbacher, Stephen Smalley, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

Casey Schaufler wrote:
> --- James Morris <jmorris@namei.org> wrote:
>
>   
>> On Fri, 15 Jun 2007, Casey Schaufler wrote:
>>
>>     
>>> --- James Morris <jmorris@namei.org> wrote:
>>>
>>>       
>>>> On my system, it takes about 1.2 seconds to label a fully checked out 
>>>> kernel source tree with ~23,000 files in this manner
>>>>         
>>> That's an eternity for that many files to be improperly labeled.
>>> If, and the "if" didn't originate with me, your policy is
>>> demonstrably correct (how do you do that?) for all domains
>>> you could claim that the action is safe, if not ideal. 
>>> I can't say if an evaluation team would buy the "safe"
>>> argument. They've been known to balk before.
>>>       
>> To clarify:
>>
>> We are discussing a scheme where the underlying SELinux labeling policy 
>> always ensures a safe label on a file, and then relabeling newly created 
>> files according to their pathnames.
>>     
>
> To counter clarify:
>
> You are saying two things:
> 1. The policy always ensures a safe label.
> 2. Files can be relabeled in a reasonable and timely manner.
>
> I have no questions about 2. It's a hack, but you've already
> acknowledged that and it will work, allowing for some potential
> cases where someone is overeager about getting a file-in-transition.
>
> Regarding 1: This is a founding premise of the arguement, that
> the "policy" is written correctly such that there is no case
> where a file gets created with an unsafe label. Given the external
> nature of the policy, and the number of attributes used within
> the policy, and the overall sophistication of the policy mechanism,
> how does one ...
>
>     a. know that a label is "safe"
>     b. know that a file will get a "safe" label
>     c. know that the policy is "correctly" written as required
>
> The question is not if fixxerupperd can set things right.
> The question is about the properly written policy that is
> required to make the mechanism worth discussing.
>
>   

There are only about 850 file type_transition rules in the policy 
shipped with RHEL and the vast majority of them are templated so this 
isn't as hard as you think. Most are things like:
   type_transition ftpd_t tmp_t : file ftpd_tmp_t;

which 1) don't require relabeling to something else and 2) very easy to 
audit. A quick look suggests that the potentially less-restrictive label 
is never chosen, for example you'll see:
   type_transition groupadd_t etc_t : file shadow_t;
   type_transition useradd_t etc_t : file shadow_t;

Instead of the default transition being etc_t they are labeled as 
shadow_t (more restrictive) and then potentially relabled to etc_t.

That said, the lack of a type_transition in this case is as important as 
having one if the default type (the parent directory) is less 
restrictive. We already have tools that analyze policy and even tools to 
warn about potential errors in policy (apol and sechecker). It might be 
a good idea to add some more analysis to these tools to point out 
potential labeling errors that can be used in automatic analysis, which 
shouldn't be hard, I'll be sure to suggest that to the setools developers.

>> There is no expectation that this scheme would be submitted for 
>> certification.
>>     
>
> De-nial.
>
>   

Several systems have gone off to ct&e and none of them use restorecond. 
These are custom build systems and relabeling is kept to a minimum and 
the applications are architected in a way that precludes this being 
necessary so I don't know what you are trying to get at here.

>> Its purpose is to merely to provide pathname-based 
>> labeling outside of the kernel.
>>     
>
> If you already have an in-kernel labeling scheme that you
> trust to make the world safe until you get around to doing
> the labeling externally you can argue that it's good enough.
> But, to quote Cinderella's Stepmother, "I said "if"".
>   

The "if" for SELinux is alot easier than you suggest. It certainly 
outweighs the disadvantages of the path based scheme IMHO.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 20:43                     ` Casey Schaufler
  2007-06-15 21:14                       ` Greg KH
@ 2007-06-18 12:47                       ` Stephen Smalley
  1 sibling, 0 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-18 12:47 UTC (permalink / raw)
  To: casey
  Cc: Greg KH, Crispin Cowan, Andreas Gruenbacher, Pavel Machek,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On Fri, 2007-06-15 at 13:43 -0700, Casey Schaufler wrote:
> --- Stephen Smalley <sds@tycho.nsa.gov> wrote:
> 
> > On Fri, 2007-06-15 at 11:01 -0700, Casey Schaufler wrote:
> > > --- Greg KH <greg@kroah.com> wrote:
> > > 
> > > 
> > > > A daemon using inotify can "instantly"[1] detect this and label the file
> > > > properly if it shows up.
> > > 
> > > In our 1995 B1 evaluation of Trusted Irix we were told in no
> > > uncertain terms that such a solution was not acceptable under
> > > the TCSEC requirements. Detection and relabel on an unlocked
> > > object creates an obvious window for exploitation. We were told
> > > that such a scheme would be considered a design flaw.
> > > 
> > > I understand that some of the Common Criteria labs are less
> > > aggressive regarding chasing down these issues than the NCSC
> > > teams were. It might not prevent an evaluation from completing
> > > today. It is still hard to explain why it's ok to have a file
> > > that's labeled incorrectly _even briefly_. It is the systems
> > > job to ensure that that does not happen.
> > 
> > Um, Casey, he is talking about how to emulate AppArmor behavior on a
> > label-based system like SELinux,
> 
> Yes. What I'm saying (or trying to) is that such an implementation
> would be flawed by design.
> 
> > not meeting B1 or LSPP or anything like that
> > (which AppArmor can't do regardless).
> 
> We're not talking about an implementation based on AppArmor. As
> you point out, we're talking about implementing name based access
> control as an extension of SELinux.

We're talking about emulating pathname-based security on SELinux.
Pathname-based security is inherently non-tranquil (names can change at
any time) and ambiguous (a single name may refer to different objects in
different namespaces, multiple names may refer to the same object in a
single namespace), and thus cannot possibly meet information flow  /
classical confinement requirements.  So using restorecond as the basis
for such an emulation loses nothing from what you already had.  Using
restorecond as the fundamental basis for the security of SELinux itself
would be a bad thing, agreed.

> > As far as general issue
> > goes, if your policy is configured such that the new file gets the most
> > restrictive label possible at creation time and then the daemon relabels
> > it to a less restrictive label if appropriate, then there is no actual
> > window of exposure.
> 
> Is it general practice to configure policy such that "the new file gets
> the most restrictive label possible at creation time"? I confess that
> my understanding of the current practice in policy generation is based
> primarily on a shouted conversation in a crowded Irish pub.
> 
> > Also, there is such a daemon, restorecond, in SELinux (policycoreutils)
> > although we avoid relying on it for anything security-critical
> > naturally.
> 
> Yes, I am aware of restorecond. I find the need for restorecond troubling.

Understand that we view it as a method of last resort, only to be
considered after trying first to:
1) Configure policy transparently to label the file correctly at
creation time (based on the creating process' label, the parent
directory label, and the kind of file), or if that fails,
2) Modify the library or application code to label the file correctly at
creation time (e.g. when multiple files that should be protected
differently are created by the same process in the same directory,
e.g. /etc/passwd vs. /etc/shadow).

> > And one could introduce the named type transition concept
> > that has been discussed in this thread without much difficulty to
> > selinux.
> 
> Yup, I see that once you accept the notion that it is OK for a
> file to be misslabeled for a bit and that having a fixxerupperd
> is sufficient it all falls out.

I think you misunderstand what I mean by named type transition here -
that is a reference to earlier discussions in this thread on extending
the SELinux type_transition statements to let the kernel directly label
new files based not only on creating process and parent directory label
but also the last component name.  With such an extension, SELinux could
directly distinguish e.g. /etc/shadow from /etc/passwd at file creation
time in the kernel without needing anything like restorecond in
userspace.  There is no temporary mislabeling with such a mechanism.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 22:24                             ` Karl MacMillan
@ 2007-06-18 13:33                               ` Stephen Smalley
  2007-06-21 15:54                                 ` Andreas Gruenbacher
  0 siblings, 1 reply; 240+ messages in thread
From: Stephen Smalley @ 2007-06-18 13:33 UTC (permalink / raw)
  To: Karl MacMillan
  Cc: Greg KH, Casey Schaufler, Crispin Cowan, Andreas Gruenbacher,
	Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Fri, 2007-06-15 at 18:24 -0400, Karl MacMillan wrote:
> On Fri, 2007-06-15 at 14:44 -0700, Greg KH wrote:
> > On Fri, Jun 15, 2007 at 05:28:35PM -0400, Karl MacMillan wrote:
> > > On Fri, 2007-06-15 at 14:14 -0700, Greg KH wrote:
> > > > On Fri, Jun 15, 2007 at 01:43:31PM -0700, Casey Schaufler wrote:
> > > > > 
> > > > > Yup, I see that once you accept the notion that it is OK for a
> > > > > file to be misslabeled for a bit and that having a fixxerupperd
> > > > > is sufficient it all falls out.
> > > > > 
> > > > > My point is that there is a segment of the security community
> > > > > that had not found this acceptable, even under the conditions
> > > > > outlined. If it meets your needs, I say run with it.
> > > > 
> > > > If that segment feels that way, then I imagine AA would not meet their
> > > > requirements today due to file handles and other ways of passing around
> > > > open files, right?
> > > > 
> > > > So, would SELinux today (without this AA-like daemon) fit the
> > > > requirements of this segment?
> > > > 
> > > 
> > > Yes - RHEL 5 is going through CC evaluations for LSPP, CAPP, and RBAC
> > > using the features of SELinux where appropriate.
> > 
> > Great, but is there the requirement in the CC stuff such that this type
> > of "delayed re-label" that an AA-like daemon would need to do cause that
> > model to not be able to be certified like your SELinux implementation
> > is?
> > 
> 
> There are two things:
> 
> 1) relabeling (non-tranquility) is very problematic in general because
> revocation is hard (and non-solved in Linux). So you would have to
> address concerns about that.

I think we need to distinguish between relying on restorecond-like
mechanisms for the security of SELinux vs. relying on them for emulating
pathname-based security.  The former would be a problem.  The latter is
no worse than pathname-based security already, because pathname-based
security is inherently ambiguous and non-tranquil, and revocation isn't
addressed fully in AA either.

> 
> 2) Whether this would pass certification depends on a lot of factors
> (like the specific requirements - CC is just a process not a single set
> of requirements). I don't know enough to really guess.
> 
> More to the point, though, the requirements in those documents are
> outdated at best. I don't think it is worth worrying over.
> 
> > As I'm guessing the default "label" for things like this already work
> > properly for SELinux, I figure we should be safe, but I don't know those
> > requirements at all.
> > 
> 
> Probably not - you would likely want it to be a label that can't be read
> or written by anything, only relabeled by the daemon.
> 
> Karl
> 
-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 23:49                       ` Greg KH
  2007-06-16  0:01                         ` david
  2007-06-16  0:18                         ` Seth Arnold
@ 2007-06-18 18:48                         ` Crispin Cowan
  2007-06-21 16:01                         ` Andreas Gruenbacher
  3 siblings, 0 replies; 240+ messages in thread
From: Crispin Cowan @ 2007-06-18 18:48 UTC (permalink / raw)
  To: Greg KH
  Cc: Pavel Machek, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

Greg KH wrote:
> On Fri, Jun 15, 2007 at 04:30:44PM -0700, Crispin Cowan wrote:
>   
>> Then there's all the other problems, such as file systems that don't
>> support extended attributes, particularly NFS3. Yes, NFS3 is vulnerable
>> to network attack, but that is not the threat AA is addressing. AA is
>> preventing an application with access to an NFS mount from accessing the
>> *entire* mount. There is lots of practical security value in this, and
>> label schemes cannot do it. Well, mostly; you could do it with a dynamic
>> labeling scheme that labels files as they are pulled into kernel memory,
>> but that requires an AA-style regexp parser in the kernel to apply the
>> labels.
>>     
> You still haven't answered Stephen's response to NFSv3, so until then,
> please don't trot out this horse.
>   
Ok then ...

Stephen Smalley wrote:
> - File systems that do not support labels:  I'm a bit surprised that you
> would advocate this given your experience in developing EA and ACL
> support for local filesystems and NFS.  The pathname-based approach in
> NFS seems even scarier than in the local case - the clients may have
> different views of the namespace than one another or the server and the
> potential for inconsistent views of the tree (particularly as it is
> being modified) during access checks is only greater in the NFS case,
> right?  It may be more expedient to implement, but is it the right
> technical approach?
I'm actually unclear on what the question is. Stephen appears to be
thinking of confining the NFS server daemon, and our intended use case
is to use AppArmor to confine applications that access data on NFS clients.

    * Each NFS *client* machine has a view of the NFS mount point that
      is consistent for that client.
    * The AA confinement is of the application accessing the NFS mount
      on the client, *not* the NFS server daemon.
    * The fact that the views of multiple clients are different from
      each other is irrelevant, because we are confining applications on
      the client, not the NFS server daemon.
    * As noted in Andreas' technical document
      http://forgeftp.novell.com//apparmor/LKML_Submission-May_07/techdoc.pdf
      there is no purpose to confining the NFS server daemon; it is a
      kernel process, and if it mis-behaves, it can completely subvert
      any kernel security policy, including AA and SELinux.

Since this point seems to be subtle, here's a motivating example.
Consider I have a diskless workstation, and my home dir /home/crispin is
NFS mounted from a big NAS server over there. I like to run my FireFox
confined, so that it only has access to /home/crispin/.mozilla/** and
/home/crispin/Downloads/** so that if my browser is compromised, the
attacker doesn't get to my /home/.ssh* stuff.

Yes, the data served over NFS is vulnerable to a local network attack,
but that is not what AA is preventing here. The threat is coming from
attacks that make the web browser misbehave.

Under SELinux, I either give the web browser access to all of
/home/crispin (the entire mount point) or none of it. Under AA, the
pathname specification works fine, we can control which directories on
the mount point the application can access.

The same argument applies to server applications that access data served
NFS mount points. Consider a large application server that hosts all my
enterprise resource management stuff, and a large NAS server that hosts
the data. Perhaps the NAS server is a Network Appliance server, not even
using a Linux file system, just supplying NFS3 mounts.

The application server is hosting both the payroll system and the
customer relationship application. The data for both are on the NetApp,
serviced via NFS to the application server. I want to confine the
payroll application to access only the payroll data, and the CRM
application to access only CRM data.

The only way SELinux could do this would be to have anticipated the
problem and store my data on separate partitions, so you could supply
separate mount points. AppArmor can just use path specifications to
confine each application to its own part of a single NFS mount point. In
a perfect world the admin would use separate mount points, AppArmor is a
tool for an imperfect world.

Crispin

-- 
Crispin Cowan, Ph.D.               http://crispincowan.com/~crispin/
Director of Software Engineering   http://novell.com
	AppArmor Chat: irc.oftc.net/#apparmor


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching
  2007-06-16  0:48                       ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
@ 2007-06-19 15:25                         ` Pavel Machek
  0 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-19 15:25 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: crispin, linux-kernel, linux-security-module

Hi!

> > In a smaller scale example, I want to share some files with a friend. I
> > can't be bothered to set up a proper access control system, so I just mv
> > the files to ~crispin/public_html/lookitme and in IRC say "get it now,
> > going away in 10 minutes" and then move it out again. Yes, you can
> > manually address this by running "restorecon ~crispin/public_html". But
> > AA does this automatically without having to run any commands.
> If you share ~crispin/public_html/lookitme by making a hard link,
> does relabeling approach work?
> I thought SELinux allows only one label for one file.
> If AA (on the top of SELinux) tries to allow different permissions to
> ~crispin/public_html/lookitme and its original location,
> either one of two pathnames won't be accessible as intended, will it?

Yes, that's a bug/feature in AA. No, selinux will not be able to emulate that
bug/feature. Yes, it is dangerous, as it makes AA mostly useless on
multiuser machines.

(ln /etc/shadow /tmp is something any user can do, and all you need is
to exploit any daemon with access to /tmp).
							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-18 13:33                               ` Stephen Smalley
@ 2007-06-21 15:54                                 ` Andreas Gruenbacher
  0 siblings, 0 replies; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-21 15:54 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Karl MacMillan, Greg KH, Casey Schaufler, Crispin Cowan,
	Pavel Machek, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Monday 18 June 2007 15:33, Stephen Smalley wrote:
> On Fri, 2007-06-15 at 18:24 -0400, Karl MacMillan wrote:
> > There are two things:
> >
> > 1) relabeling (non-tranquility) is very problematic in general because
> > revocation is hard (and non-solved in Linux). So you would have to
> > address concerns about that.
>
> I think we need to distinguish between relying on restorecond-like
> mechanisms for the security of SELinux vs. relying on them for emulating
> pathname-based security.  The former would be a problem.  The latter is
> no worse than pathname-based security already, because pathname-based
> security is inherently ambiguous and non-tranquil, and revocation isn't
> addressed fully in AA either.

Emulation using lazy relabeling introduces a window where the files have the 
wrong label. In those windows, the pathname based policy is being violated, 
and unintended side effects are suddenly possible. This includes granting of 
access to files that applications should no longer have access to according 
to the pathname based policy, which would be similar to what happens when a 
process keeps an open file handle right now. But it also includes denial of 
access to files that applications should have access to, and this might cause 
those applications to fail. So this is where relabeling from user space is 
much worse.

The only way to get rid of the denial of service problem would be to make the 
rename and relabel an atomic operation. The time this can take is huge 
though, so that's not acceptable.

Another, less catastrophic problem is that rename has always been relatively 
fast and inexpensive, and I'm sure plenty of applications rely on this 
performance characteristic. Making rename a very expensive operation in at 
least some cases (which are more than theoretical) would hurt those 
applications, and nothing much could be done about it.

Adding better new-file mechanisms to SELinux probably is a good idea, and it 
would weaken the SELinux seurity model for all I can tell. It doesn't address 
the relabeling problem though.

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-15 23:49                       ` Greg KH
                                           ` (2 preceding siblings ...)
  2007-06-18 18:48                         ` Crispin Cowan
@ 2007-06-21 16:01                         ` Andreas Gruenbacher
  2007-06-21 17:59                           ` Pavel Machek
  3 siblings, 1 reply; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-21 16:01 UTC (permalink / raw)
  To: Greg KH
  Cc: Crispin Cowan, Pavel Machek, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Saturday 16 June 2007 01:49, Greg KH wrote:
> But for those types of models that do not map well to internal kernel
> structures, perhaps they should be modeled on top of a security system that
> does handle the internal kernel representation of things in the way the
> kernel works.

How exactly are struct vfsmount and struct dentry not in-kernel structures?

Andreas

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  0:02                       ` Pavel Machek
@ 2007-06-21 16:08                         ` Lars Marowsky-Bree
  2007-06-21 18:33                           ` Pavel Machek
  0 siblings, 1 reply; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-21 16:08 UTC (permalink / raw)
  To: Pavel Machek, Crispin Cowan
  Cc: Greg KH, Andreas Gruenbacher, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

I've caught up on this thread with growing disbelief while reading the
mails, so much that I've found it hard to decide where to reply to.

So people are claiming that AA is ugly, because it introduces pathnames
and possibly a regex interpreter. Ok, taste differs. We've got many
different flavours of filesystems in the kernel because of that.

However, the suggested cure makes me cringe.

You're saying that relabeling file(s) from user-space after a rename is
a possible solution.

This breaks POSIX - renames must be atomic. It is possibly insecure; if
this is fixed by making a rename automatically default to restrictive
permissions, it'll be even more inconvenient. It will break applications
which expect to be able to access the file(s) immediately after a
rename. It is slow, and can possibly cause a lot of disk access.
Possibly over NFS or via slow disks. By going through user-space - which
could block and introduce all sorts of memory deadlocks (compared to
that deadlock, a regex is harmless.) (I also wonder how you propose to
relabel files on a r/o mount if the policy changes, btw; or if the NFS
mount is made available on several nodes w/different permissions.) AA
only enforces user-space defined policy - the argument that policy
doesn't belong into the kernel is bull. Adding a wrapper to glibc to
block until relabeling is complete?

"Let's first do the implementation and later worry about performance."?
"The timing window is neglible."? "30 minutes during installation does
not seem silly."?

You _must_ be kidding. The cure is worse than the problem.

If that is the only way to implement AA on top of SELinux - and so far,
noone has made a better suggestion - I'm convinced that AA has technical
merit: it does something the on-disk label based approach cannot handle,
and for which there is demand.

The code has improved, and continues to improve, to meet all the coding
style feedback except the bits which are essential to AA's function
(like the pathname lookup and the regex parser; though I'm sure that in
particular the later one could be swapped for a less complex matcher as
well). It certainly isn't worse than many other areas of the kernel.

You're pointing to each other's opposition to the features - that, my
dear gentlemen, is a circular argument. One of you could readily break
the chain.

This is trying to get rid of AA for the sake of it, masquerading as
technical reasons. At least fucking admit it. Don't lie. This is
distasteful.


Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 16:01                         ` Andreas Gruenbacher
@ 2007-06-21 17:59                           ` Pavel Machek
  0 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-21 17:59 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Greg KH, Crispin Cowan, Stephen Smalley, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Thu 2007-06-21 18:01:05, Andreas Gruenbacher wrote:
> On Saturday 16 June 2007 01:49, Greg KH wrote:
> > But for those types of models that do not map well to internal kernel
> > structures, perhaps they should be modeled on top of a security system that
> > does handle the internal kernel representation of things in the way the
> > kernel works.
> 
> How exactly are struct vfsmount and struct dentry not in-kernel structures?

That's what greg is talking about, AFAICT. Normal kernel code uses
struct vfsmount + struct dentry.

AA uses... guess what... char pathname[HUGE_VALUE].
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 16:08                         ` Lars Marowsky-Bree
@ 2007-06-21 18:33                           ` Pavel Machek
  2007-06-21 19:24                             ` Lars Marowsky-Bree
  2007-06-21 19:30                             ` david
  0 siblings, 2 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-21 18:33 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: Crispin Cowan, Greg KH, Andreas Gruenbacher, Stephen Smalley,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

Hi!

> I've caught up on this thread with growing disbelief while reading the
> mails, so much that I've found it hard to decide where to reply to.
> 
> So people are claiming that AA is ugly, because it introduces pathnames
> and possibly a regex interpreter. Ok, taste differs. We've got many
> different flavours of filesystems in the kernel because of that.
> 
> However, the suggested cure makes me cringe.
> 
> You're saying that relabeling file(s) from user-space after a rename is
> a possible solution.
> 
> This breaks POSIX - renames must be atomic. It is possibly insecure; if
> this is fixed by making a rename automatically default to restrictive
> permissions, it'll be even more inconvenient. It will break
> applications

inconvenient, yes, insecure, no.

I believe AA breaks POSIX, already. rename() is not expected to change
permissions on target, nor is link link. And yes, both of these make
AA insecure.

> You _must_ be kidding. The cure is worse than the problem.

Possibly.

> If that is the only way to implement AA on top of SELinux - and so far,
> noone has made a better suggestion - I'm convinced that AA has technical
> merit: it does something the on-disk label based approach cannot handle,
> and for which there is demand.

What demand? SELinux is superior to AA, and there was very little
demand for AA. Compare demand for reiser4 or suspend2 with demand for
AA.

> The code has improved, and continues to improve, to meet all the coding
> style feedback except the bits which are essential to AA's function

Which are exactly the bits Christoph Hellwig and Al Viro
vetoed. http://www.uwsg.iu.edu/hypermail/linux/kernel/0706.1/2587.html
. I believe it takes more than "2 users want it" to overcome veto of
VFS maintainer.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 18:33                           ` Pavel Machek
@ 2007-06-21 19:24                             ` Lars Marowsky-Bree
  2007-06-21 19:42                               ` James Morris
  2007-06-21 20:07                               ` Pavel Machek
  2007-06-21 19:30                             ` david
  1 sibling, 2 replies; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-21 19:24 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Crispin Cowan, Greg KH, Andreas Gruenbacher, Stephen Smalley,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On 2007-06-21T20:33:11, Pavel Machek <pavel@ucw.cz> wrote:

> inconvenient, yes, insecure, no.

Well, only if you use the most restrictive permissions. And then you'll
suddenly hit failure cases which you didn't expect to, which can
possibly cause another exploit to become visible.

> I believe AA breaks POSIX, already. rename() is not expected to change
> permissions on target, nor is link link. And yes, both of these make
> AA insecure.

AA is supposed to allow valid access patterns, so for non-buggy apps +
policies, the rename will be fine and does not change the (observed)
permissions.

The time window in the rename+relabel approach however introduces a slot
where permissions are not consistent. This is a different case.

> > You _must_ be kidding. The cure is worse than the problem.
> Possibly.

Yes.

> > If that is the only way to implement AA on top of SELinux - and so far,
> > noone has made a better suggestion - I'm convinced that AA has technical
> > merit: it does something the on-disk label based approach cannot handle,
> > and for which there is demand.
> What demand? SELinux is superior to AA, and there was very little
> demand for AA. Compare demand for reiser4 or suspend2 with demand for
> AA.

SELinux is superior to AA for a certain scenario of use cases; as we can
see here, it is not superior to AA for _all_ use cases.

> > The code has improved, and continues to improve, to meet all the coding
> > style feedback except the bits which are essential to AA's function
> Which are exactly the bits Christoph Hellwig and Al Viro
> vetoed. http://www.uwsg.iu.edu/hypermail/linux/kernel/0706.1/2587.html
> . I believe it takes more than "2 users want it" to overcome veto of
> VFS maintainer.

A veto is not a technical argument. All technical arguments (except for
"path name is ugly, yuk yuk!") have been addressed, have they not?



Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 18:33                           ` Pavel Machek
  2007-06-21 19:24                             ` Lars Marowsky-Bree
@ 2007-06-21 19:30                             ` david
  2007-06-21 19:35                               ` Lars Marowsky-Bree
  2007-06-21 19:52                               ` Pavel Machek
  1 sibling, 2 replies; 240+ messages in thread
From: david @ 2007-06-21 19:30 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Lars Marowsky-Bree, Crispin Cowan, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Thu, 21 Jun 2007, Pavel Machek wrote:

>> If that is the only way to implement AA on top of SELinux - and so far,
>> noone has made a better suggestion - I'm convinced that AA has technical
>> merit: it does something the on-disk label based approach cannot handle,
>> and for which there is demand.
>
> What demand? SELinux is superior to AA, and there was very little
> demand for AA. Compare demand for reiser4 or suspend2 with demand for
> AA.

well, if you _really_ want people who are interested in this to do weekly 
"why isn't it merged yet you $%#$%# developers" threads that can be 
arranged.

the people who want this have been trying to be patient and let the system 
work. if it takes people being pests to get something implemented it can 
be done, but I don't think other people on the list will appriciate this.

>> The code has improved, and continues to improve, to meet all the coding
>> style feedback except the bits which are essential to AA's function
>
> Which are exactly the bits Christoph Hellwig and Al Viro
> vetoed. http://www.uwsg.iu.edu/hypermail/linux/kernel/0706.1/2587.html
> . I believe it takes more than "2 users want it" to overcome veto of
> VFS maintainer.

so you are saying that _any_ pathname based solution is not acceptable to 
the kernel, no matter what?

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 19:30                             ` david
@ 2007-06-21 19:35                               ` Lars Marowsky-Bree
  2007-06-21 19:52                               ` Pavel Machek
  1 sibling, 0 replies; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-21 19:35 UTC (permalink / raw)
  To: david, Pavel Machek
  Cc: Crispin Cowan, Greg KH, Andreas Gruenbacher, Stephen Smalley,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On 2007-06-21T12:30:08, david@lang.hm wrote:

> well, if you _really_ want people who are interested in this to do weekly 
> "why isn't it merged yet you $%#$%# developers" threads that can be 
> arranged.
> 
> the people who want this have been trying to be patient and let the system 
> work. if it takes people being pests to get something implemented it can 
> be done, but I don't think other people on the list will appriciate this.

Please. We're so not going down _that_ route.



^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 19:24                             ` Lars Marowsky-Bree
@ 2007-06-21 19:42                               ` James Morris
  2007-06-21 19:54                                 ` Lars Marowsky-Bree
  2007-06-21 20:07                               ` Pavel Machek
  1 sibling, 1 reply; 240+ messages in thread
From: James Morris @ 2007-06-21 19:42 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: Pavel Machek, Crispin Cowan, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On Thu, 21 Jun 2007, Lars Marowsky-Bree wrote:

> A veto is not a technical argument. All technical arguments (except for
> "path name is ugly, yuk yuk!") have been addressed, have they not?

AppArmor doesn't actually provide confinement, because it only operates on 
filesystem objects.

What you define in AppArmor policy does _not_ reflect the actual 
confinement properties of the policy.  Applications can simply use other 
mechanisms to access objects, and the policy is effectively meaningless.

You might define this as a non-technical issue, but the fact that AppArmor 
simply does not and can not work is a fairly significant consideration, I 
would imagine.



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 19:30                             ` david
  2007-06-21 19:35                               ` Lars Marowsky-Bree
@ 2007-06-21 19:52                               ` Pavel Machek
  1 sibling, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-21 19:52 UTC (permalink / raw)
  To: david
  Cc: Lars Marowsky-Bree, Crispin Cowan, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

Hi!

> >>The code has improved, and continues to improve, to meet all the coding
> >>style feedback except the bits which are essential to AA's function
> >
> >Which are exactly the bits Christoph Hellwig and Al Viro
> >vetoed. http://www.uwsg.iu.edu/hypermail/linux/kernel/0706.1/2587.html
> >. I believe it takes more than "2 users want it" to overcome veto of
> >VFS maintainer.
> 
> so you are saying that _any_ pathname based solution is not acceptable to 
> the kernel, no matter what?

You'd have to ask Christoph the same question.

AFAICT, reconstructing full path then basing security on that is a
no-no.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 19:42                               ` James Morris
@ 2007-06-21 19:54                                 ` Lars Marowsky-Bree
  2007-06-21 20:59                                   ` Stephen Smalley
  0 siblings, 1 reply; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-21 19:54 UTC (permalink / raw)
  To: James Morris
  Cc: Pavel Machek, Crispin Cowan, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

On 2007-06-21T15:42:28, James Morris <jmorris@namei.org> wrote:

> > A veto is not a technical argument. All technical arguments (except for
> > "path name is ugly, yuk yuk!") have been addressed, have they not?
> AppArmor doesn't actually provide confinement, because it only operates on 
> filesystem objects.
> 
> What you define in AppArmor policy does _not_ reflect the actual 
> confinement properties of the policy.  Applications can simply use other 
> mechanisms to access objects, and the policy is effectively meaningless.

Only if they have access to another process which provides them with
that data.

And now, yes, I know AA doesn't mediate IPC or networking (yet), but
that's a missing feature, not broken by design.

> You might define this as a non-technical issue, but the fact that AppArmor 
> simply does not and can not work is a fairly significant consideration, I 
> would imagine.

If I restrict my Mozilla to not access my on-disk mail folder, it can't
get there. (Barring bugs in programs which Mozilla is allowed to run
unconfined, sure.)

If the argument is that AA provides somewhat different semantics - and
for some use cases "weaker" ones - than SE Linux, that is undoubtly
true. However, it appears to be the case that those are the differences
which make AA's model different from SELinux as well, so it appears a
trade-off best left to the admin / user to choose what fits their needs
best.


Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 19:24                             ` Lars Marowsky-Bree
  2007-06-21 19:42                               ` James Morris
@ 2007-06-21 20:07                               ` Pavel Machek
  2007-06-21 20:21                                 ` Lars Marowsky-Bree
  1 sibling, 1 reply; 240+ messages in thread
From: Pavel Machek @ 2007-06-21 20:07 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: Crispin Cowan, Greg KH, Andreas Gruenbacher, Stephen Smalley,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

Hi!

> > I believe AA breaks POSIX, already. rename() is not expected to change
> > permissions on target, nor is link link. And yes, both of these make
> > AA insecure.
> 
> AA is supposed to allow valid access patterns, so for non-buggy apps +
> policies, the rename will be fine and does not change the (observed)
> permissions.

That still breaks POSIX, right? Hopefully it will not break any apps,
but...

> > > If that is the only way to implement AA on top of SELinux - and so far,
> > > noone has made a better suggestion - I'm convinced that AA has technical
> > > merit: it does something the on-disk label based approach cannot handle,
> > > and for which there is demand.
> > What demand? SELinux is superior to AA, and there was very little
> > demand for AA. Compare demand for reiser4 or suspend2 with demand for
> > AA.
> 
> SELinux is superior to AA for a certain scenario of use cases; as we can
> see here, it is not superior to AA for _all_ use cases.

The scenario where it does not seem superior is "I have system with AA
here and I'd like to keep using it".

> > > The code has improved, and continues to improve, to meet all the coding
> > > style feedback except the bits which are essential to AA's function
> > Which are exactly the bits Christoph Hellwig and Al Viro
> > vetoed. http://www.uwsg.iu.edu/hypermail/linux/kernel/0706.1/2587.html
> > . I believe it takes more than "2 users want it" to overcome veto of
> > VFS maintainer.
> 
> A veto is not a technical argument. All technical arguments (except for
> "path name is ugly, yuk yuk!") have been addressed, have they not?

There still is "it does not work with long pathnames".

Plus IIRC we have something like "AA has to allocate path-sized
buffers along every syscall".

I guess Al Viro or Christoph Hellwig would be able to detail on
that. I don't think they are vetoing stuff for fun.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 20:07                               ` Pavel Machek
@ 2007-06-21 20:21                                 ` Lars Marowsky-Bree
  2007-06-21 23:25                                   ` John Johansen
  0 siblings, 1 reply; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-21 20:21 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Crispin Cowan, Greg KH, Andreas Gruenbacher, Stephen Smalley,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

On 2007-06-21T22:07:40, Pavel Machek <pavel@ucw.cz> wrote:

> > AA is supposed to allow valid access patterns, so for non-buggy apps +
> > policies, the rename will be fine and does not change the (observed)
> > permissions.
> That still breaks POSIX, right? Hopefully it will not break any apps,
> but...

No, it does not break POSIX.

Unless, of course, there's a bug in the policy or in the program. Bugs
are generally not covered by POSIX, for some strange reason.

(The argument that POSIX codifies implementation bugs in Unix(tm)
implementations of the time non-withstanding.)

> > A veto is not a technical argument. All technical arguments (except for
> > "path name is ugly, yuk yuk!") have been addressed, have they not?
> There still is "it does not work with long pathnames".
> 
> Plus IIRC we have something like "AA has to allocate path-sized
> buffers along every syscall".

That is an implementation bug though. I'm sure we have other bugs in the
kernel too - this isn't a design flaw. 

(If people are allowed to thinair solutions for implementing AA on top
of SELinux, I can thinair that this can be solved by reverse-matching
the dentry tree against the policy as the path is traversed and
constructed, requiring a constant sized buffer.)



Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 19:54                                 ` Lars Marowsky-Bree
@ 2007-06-21 20:59                                   ` Stephen Smalley
  2007-06-21 21:17                                     ` Lars Marowsky-Bree
                                                       ` (3 more replies)
  0 siblings, 4 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-21 20:59 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Thu, 2007-06-21 at 21:54 +0200, Lars Marowsky-Bree wrote:
> On 2007-06-21T15:42:28, James Morris <jmorris@namei.org> wrote:
> 
> > > A veto is not a technical argument. All technical arguments (except for
> > > "path name is ugly, yuk yuk!") have been addressed, have they not?
> > AppArmor doesn't actually provide confinement, because it only operates on 
> > filesystem objects.
> > 
> > What you define in AppArmor policy does _not_ reflect the actual 
> > confinement properties of the policy.  Applications can simply use other 
> > mechanisms to access objects, and the policy is effectively meaningless.
> 
> Only if they have access to another process which provides them with
> that data.

Or can access the data under a different path to which their profile
does give them access, whether in its final destination or in some
temporary file processed along the way.

> And now, yes, I know AA doesn't mediate IPC or networking (yet), but
> that's a missing feature, not broken by design.

The incomplete mediation flows from the design, since the pathname-based
mediation doesn't generalize to cover all objects unlike label- or
attribute-based mediation.  And the "use the natural abstraction for
each object type" approach likewise doesn't yield any general model or
anything that you can analyze systematically for data flow.

The emphasis on never modifying applications for security in AA likewise
has an adverse impact here, as you will ultimately have to deal with
application mediation of access to their own objects and operations not
directly visible to the kernel (as we have already done in SELinux for
D-BUS and others and are doing for X).  Otherwise, your "protection" of
desktop applications is easily subverted.

> > You might define this as a non-technical issue, but the fact that AppArmor 
> > simply does not and can not work is a fairly significant consideration, I 
> > would imagine.
> 
> If I restrict my Mozilla to not access my on-disk mail folder, it can't
> get there. (Barring bugs in programs which Mozilla is allowed to run
> unconfined, sure.)

Um, no.  It might not be able to directly open files via that path, but
showing that it can never read or write your mail is a rather different
matter.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 20:59                                   ` Stephen Smalley
@ 2007-06-21 21:17                                     ` Lars Marowsky-Bree
  2007-06-22  0:16                                       ` Joshua Brindle
  2007-06-22 11:19                                       ` Stephen Smalley
  2007-06-22  0:34                                     ` Chris Mason
                                                       ` (2 subsequent siblings)
  3 siblings, 2 replies; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-21 21:17 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On 2007-06-21T16:59:54, Stephen Smalley <sds@tycho.nsa.gov> wrote:

> Or can access the data under a different path to which their profile
> does give them access, whether in its final destination or in some
> temporary file processed along the way.

Well, yes. That is intentional.

Your point is?

> The emphasis on never modifying applications for security in AA likewise
> has an adverse impact here, as you will ultimately have to deal with
> application mediation of access to their own objects and operations not
> directly visible to the kernel (as we have already done in SELinux for
> D-BUS and others and are doing for X).  Otherwise, your "protection" of
> desktop applications is easily subverted.

That is an interesting argument, but not what we're discussing here.
We're arguing filesystem access mediation.

> Um, no.  It might not be able to directly open files via that path, but
> showing that it can never read or write your mail is a rather different
> matter.

Yes. Your use case is different than mine.



Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 20:21                                 ` Lars Marowsky-Bree
@ 2007-06-21 23:25                                   ` John Johansen
  0 siblings, 0 replies; 240+ messages in thread
From: John Johansen @ 2007-06-21 23:25 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: Pavel Machek, Crispin Cowan, Greg KH, Andreas Gruenbacher,
	Stephen Smalley, jjohansen, linux-kernel, linux-security-module,
	linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 1170 bytes --]

On Thu, Jun 21, 2007 at 10:21:07PM +0200, Lars Marowsky-Bree wrote:
> On 2007-06-21T22:07:40, Pavel Machek <pavel@ucw.cz> wrote:
> 
> > 
> > Plus IIRC we have something like "AA has to allocate path-sized
> > buffers along every syscall".
> 
> That is an implementation bug though. I'm sure we have other bugs in the
> kernel too - this isn't a design flaw. 
> 
> (If people are allowed to thinair solutions for implementing AA on top
> of SELinux, I can thinair that this can be solved by reverse-matching
> the dentry tree against the policy as the path is traversed and
> constructed, requiring a constant sized buffer.)
> 
Indeed there are a few solutions to "fix" this implementation "bug",
of which reverse matching is one.  For reverse matching the policy
tables would become larger.   Reverse matching wouldn't need any
additional buffer for enforcement but would still fall back to d_path
for logging.

But we would still require the changes to the vfs and also a way to
safely walk the tree backwards.  So we would need to either export the
namespace semaphore or add a generic walking function which we could
pass a hook function to.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 21:17                                     ` Lars Marowsky-Bree
@ 2007-06-22  0:16                                       ` Joshua Brindle
  2007-06-22  0:19                                         ` Lars Marowsky-Bree
  2007-06-22  0:28                                         ` david
  2007-06-22 11:19                                       ` Stephen Smalley
  1 sibling, 2 replies; 240+ messages in thread
From: Joshua Brindle @ 2007-06-22  0:16 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: Stephen Smalley, James Morris, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

Lars Marowsky-Bree wrote:
> On 2007-06-21T16:59:54, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> <snip>
>
>   
>> Um, no.  It might not be able to directly open files via that path, but
>> showing that it can never read or write your mail is a rather different
>> matter.
>>     
>
> Yes. Your use case is different than mine.
>   

So.. your use case is what? If an AA user asked you to protect his mail 
from his browser I'm sure you'd truthfully answer "no, we can't do that 
but we can protect the path to your mail from your browser".. I think 
not. One need only look at the wonderful marketing literature for AA to 
see what you are telling people it can do, and your above statement 
isn't consistent with that, sorry.


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  0:16                                       ` Joshua Brindle
@ 2007-06-22  0:19                                         ` Lars Marowsky-Bree
  2007-06-22  0:28                                         ` david
  1 sibling, 0 replies; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-22  0:19 UTC (permalink / raw)
  To: Joshua Brindle
  Cc: Stephen Smalley, James Morris, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On 2007-06-21T20:16:25, Joshua Brindle <method@manicmethod.com> wrote:

> not. One need only look at the wonderful marketing literature for AA to 
> see what you are telling people it can do, and your above statement 
> isn't consistent with that, sorry.

I'm sorry. I don't work in marketing.


-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  0:16                                       ` Joshua Brindle
  2007-06-22  0:19                                         ` Lars Marowsky-Bree
@ 2007-06-22  0:28                                         ` david
  2007-06-22  3:45                                           ` Joshua Brindle
  1 sibling, 1 reply; 240+ messages in thread
From: david @ 2007-06-22  0:28 UTC (permalink / raw)
  To: Joshua Brindle
  Cc: Lars Marowsky-Bree, Stephen Smalley, James Morris, Pavel Machek,
	Crispin Cowan, Greg KH, Andreas Gruenbacher, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Thu, 21 Jun 2007, Joshua Brindle wrote:

> Lars Marowsky-Bree wrote:
>>  On 2007-06-21T16:59:54, Stephen Smalley <sds@tycho.nsa.gov> wrote:
>>  <snip>
>>
>> 
>> >  Um, no.  It might not be able to directly open files via that path, but
>> >  showing that it can never read or write your mail is a rather different
>> >  matter.
>> > 
>>
>>  Yes. Your use case is different than mine.
>> 
>
> So.. your use case is what? If an AA user asked you to protect his mail from 
> his browser I'm sure you'd truthfully answer "no, we can't do that but we can 
> protect the path to your mail from your browser".. I think not. One need only 
> look at the wonderful marketing literature for AA to see what you are telling 
> people it can do, and your above statement isn't consistent with that, sorry.

remember, the policies define a white-list

so if a hacker wants to have mozilla access the mail files he needs to get 
some other process on the sysstem to create a link or move a file to a 
path that mozilla does have access to. until that is done there is no way 
for mozilla to access the mail through the filesystem.

other programs could be run that would give mozilla access to the mail 
contents, but it would be through some other path that the policy 
permitted mozilla accessing in the first place.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 20:59                                   ` Stephen Smalley
  2007-06-21 21:17                                     ` Lars Marowsky-Bree
@ 2007-06-22  0:34                                     ` Chris Mason
  2007-06-22  1:06                                       ` James Morris
  2007-06-22  8:06                                     ` John Johansen
  2007-06-24 20:35                                     ` David Wagner
  3 siblings, 1 reply; 240+ messages in thread
From: Chris Mason @ 2007-06-22  0:34 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Lars Marowsky-Bree, James Morris, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Thu, Jun 21, 2007 at 04:59:54PM -0400, Stephen Smalley wrote:
> On Thu, 2007-06-21 at 21:54 +0200, Lars Marowsky-Bree wrote:
> > On 2007-06-21T15:42:28, James Morris <jmorris@namei.org> wrote:
> > 
> > > > A veto is not a technical argument. All technical arguments (except for
> > > > "path name is ugly, yuk yuk!") have been addressed, have they not?
> > > AppArmor doesn't actually provide confinement, because it only operates on 
> > > filesystem objects.
> > > 
> > > What you define in AppArmor policy does _not_ reflect the actual 
> > > confinement properties of the policy.  Applications can simply use other 
> > > mechanisms to access objects, and the policy is effectively meaningless.
> > 
> > Only if they have access to another process which provides them with
> > that data.
> 
> Or can access the data under a different path to which their profile
> does give them access, whether in its final destination or in some
> temporary file processed along the way.
> 
> > And now, yes, I know AA doesn't mediate IPC or networking (yet), but
> > that's a missing feature, not broken by design.
> 
> The incomplete mediation flows from the design, since the pathname-based
> mediation doesn't generalize to cover all objects unlike label- or
> attribute-based mediation.  And the "use the natural abstraction for
> each object type" approach likewise doesn't yield any general model or
> anything that you can analyze systematically for data flow.

This feels quite a lot like a repeat of the discussion at the kernel
summit.  There are valid uses for path based security, and if they don't
fit your needs, please don't use them.  But, path based semantics alone
are not a valid reason to shut out AA.

-chris


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  0:34                                     ` Chris Mason
@ 2007-06-22  1:06                                       ` James Morris
  2007-06-22  4:17                                         ` Crispin Cowan
                                                           ` (3 more replies)
  0 siblings, 4 replies; 240+ messages in thread
From: James Morris @ 2007-06-22  1:06 UTC (permalink / raw)
  To: Chris Mason
  Cc: Stephen Smalley, Lars Marowsky-Bree, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Thu, 21 Jun 2007, Chris Mason wrote:

> > The incomplete mediation flows from the design, since the pathname-based
> > mediation doesn't generalize to cover all objects unlike label- or
> > attribute-based mediation.  And the "use the natural abstraction for
> > each object type" approach likewise doesn't yield any general model or
> > anything that you can analyze systematically for data flow.
> 
> This feels quite a lot like a repeat of the discussion at the kernel
> summit.  There are valid uses for path based security, and if they don't
> fit your needs, please don't use them.  But, path based semantics alone
> are not a valid reason to shut out AA.

The validity or otherwise of pathname access control is not being 
discussed here.

The point is that the pathname model does not generalize, and that 
AppArmor's inability to provide adequate coverage of the system is a 
design issue arising from this.

Recall that the question asked by Lars was whether there were any 
outstanding technical issues relating to AppArmor.

AppArmor does not and can not provide the level of confinement claimed by 
the documentation, and its policy does not reflect its actual confinement 
properties.  That's kind of a technical issue, right?


- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  0:28                                         ` david
@ 2007-06-22  3:45                                           ` Joshua Brindle
  2007-06-22  5:07                                             ` david
  2007-06-22 10:49                                             ` Lars Marowsky-Bree
  0 siblings, 2 replies; 240+ messages in thread
From: Joshua Brindle @ 2007-06-22  3:45 UTC (permalink / raw)
  To: david
  Cc: Lars Marowsky-Bree, Stephen Smalley, James Morris, Pavel Machek,
	Crispin Cowan, Greg KH, Andreas Gruenbacher, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

david@lang.hm wrote:
> On Thu, 21 Jun 2007, Joshua Brindle wrote:
>
>> Lars Marowsky-Bree wrote:
>>>  On 2007-06-21T16:59:54, Stephen Smalley <sds@tycho.nsa.gov> wrote:
>>>  <snip>
>>>
>>>
>>> >  Um, no.  It might not be able to directly open files via that 
>>> path, but
>>> >  showing that it can never read or write your mail is a rather 
>>> different
>>> >  matter.
>>> >
>>>  Yes. Your use case is different than mine.
>>>
>>
>> So.. your use case is what? If an AA user asked you to protect his 
>> mail from his browser I'm sure you'd truthfully answer "no, we can't 
>> do that but we can protect the path to your mail from your browser".. 
>> I think not. One need only look at the wonderful marketing literature 
>> for AA to see what you are telling people it can do, and your above 
>> statement isn't consistent with that, sorry.
>
> remember, the policies define a white-list
>

Except for unconfined processes.

> so if a hacker wants to have mozilla access the mail files he needs to 
> get some other process on the sysstem to create a link or move a file 
> to a path that mozilla does have access to. until that is done there 
> is no way for mozilla to access the mail through the filesystem.
>
> other programs could be run that would give mozilla access to the mail 
> contents, but it would be through some other path that the policy 
> permitted mozilla accessing in the first place.
>
Or through IPC or the network, that is the point, filesystem only 
coverage doesn't cut it; there is no way to say the browser can't access 
the users mail in AA, and there never will be.


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  1:06                                       ` James Morris
@ 2007-06-22  4:17                                         ` Crispin Cowan
  2007-06-22 12:20                                           ` Stephen Smalley
  2007-06-22  7:40                                         ` John Johansen
                                                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 240+ messages in thread
From: Crispin Cowan @ 2007-06-22  4:17 UTC (permalink / raw)
  To: James Morris
  Cc: Chris Mason, Stephen Smalley, Lars Marowsky-Bree, Pavel Machek,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

James Morris wrote:
> On Thu, 21 Jun 2007, Chris Mason wrote:  
>>> The incomplete mediation flows from the design, since the pathname-based
>>> mediation doesn't generalize to cover all objects unlike label- or
>>> attribute-based mediation.  And the "use the natural abstraction for
>>> each object type" approach likewise doesn't yield any general model or
>>> anything that you can analyze systematically for data flow.
>>>       
>> This feels quite a lot like a repeat of the discussion at the kernel
>> summit.  There are valid uses for path based security, and if they don't
>> fit your needs, please don't use them.  But, path based semantics alone
>> are not a valid reason to shut out AA.
>>     
> The validity or otherwise of pathname access control is not being 
> discussed here.
>
> The point is that the pathname model does not generalize, and that 
> AppArmor's inability to provide adequate coverage of the system is a 
> design issue arising from this.
>   
The above two paragraphs appear to contradict each other.

> Recall that the question asked by Lars was whether there were any 
> outstanding technical issues relating to AppArmor.
>
> AppArmor does not and can not provide the level of confinement claimed by 
> the documentation, and its policy does not reflect its actual confinement 
> properties.  That's kind of a technical issue, right?
>   
So if the document said "confinement with respect to direct file access
and POSIX.1e capabilities" and that list got extended as AA got new
confinement features, would that address your issue?

Crispin

-- 
Crispin Cowan, Ph.D.               http://crispincowan.com/~crispin/
Director of Software Engineering   http://novell.com
	AppArmor Chat: irc.oftc.net/#apparmor



^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  3:45                                           ` Joshua Brindle
@ 2007-06-22  5:07                                             ` david
  2007-06-22 10:49                                             ` Lars Marowsky-Bree
  1 sibling, 0 replies; 240+ messages in thread
From: david @ 2007-06-22  5:07 UTC (permalink / raw)
  To: Joshua Brindle
  Cc: Lars Marowsky-Bree, Stephen Smalley, James Morris, Pavel Machek,
	Crispin Cowan, Greg KH, Andreas Gruenbacher, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Thu, 21 Jun 2007, Joshua Brindle wrote:

> david@lang.hm wrote:
>>  On Thu, 21 Jun 2007, Joshua Brindle wrote:
>> 
>> >  Lars Marowsky-Bree wrote:
>> > >   On 2007-06-21T16:59:54, Stephen Smalley <sds@tycho.nsa.gov> wrote:
>> > >   <snip>
>> > > 
>> > > 
>> > > >   Um, no.  It might not be able to directly open files via that 
>> > >  path, but
>> > > >   showing that it can never read or write your mail is a rather 
>> > >  different
>> > > >   matter.
>> > > > 
>> > >   Yes. Your use case is different than mine.
>> > > 
>> > 
>> >  So.. your use case is what? If an AA user asked you to protect his mail 
>> >  from his browser I'm sure you'd truthfully answer "no, we can't do that 
>> >  but we can protect the path to your mail from your browser".. I think 
>> >  not. One need only look at the wonderful marketing literature for AA to 
>> >  see what you are telling people it can do, and your above statement 
>> >  isn't consistent with that, sorry.
>>
>>  remember, the policies define a white-list
>> 
>
> Except for unconfined processes.

correct, but we are talking about what a confined process can get to 
without assistance from an unconfined process.

>>  so if a hacker wants to have mozilla access the mail files he needs to get
>>  some other process on the sysstem to create a link or move a file to a
>>  path that mozilla does have access to. until that is done there is no way
>>  for mozilla to access the mail through the filesystem.
>>
>>  other programs could be run that would give mozilla access to the mail
>>  contents, but it would be through some other path that the policy
>>  permitted mozilla accessing in the first place.
>> 
> Or through IPC or the network, that is the point, filesystem only coverage 
> doesn't cut it; there is no way to say the browser can't access the users 
> mail in AA, and there never will be.

AA can be extended to cover these things in the future.

remember 'release early release often'?
how about 'perfect is the enemy of good enoug'?

at this point they're trying to get the initial implementation in so that 
people can start takeing advantage of it. As a side effect the cost of 
maintaining it will decrease, and they can put effort into planning future 
enhancements.

besides, as far as the network communication goes, doesn't netfilter now 
have a way to make rules for specific processes? if they don't then it 
could be added, but the details of the implementation would probably be 
very different from the current AA file controls.

how does delaying the acceptance of the current implementation encourage 
the additional features being added?

but to answer your two comments.

how does mozilla access your mail over the network without first capturing 
your password from somewhere?

as far as IPC goes, unix sockets are unavailable (AA as-is will control 
them), so you must be talking about signals or shared memory as the IPC 
mechanisms that mozilla would use to access your mail.

please explain to me what mail client you are useing that exposes your 
mail via these mechinsms.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  1:06                                       ` James Morris
  2007-06-22  4:17                                         ` Crispin Cowan
@ 2007-06-22  7:40                                         ` John Johansen
  2007-06-22 12:17                                         ` Chris Mason
  2007-06-24 21:20                                         ` David Wagner
  3 siblings, 0 replies; 240+ messages in thread
From: John Johansen @ 2007-06-22  7:40 UTC (permalink / raw)
  To: James Morris
  Cc: Chris Mason, Stephen Smalley, Lars Marowsky-Bree, Pavel Machek,
	Crispin Cowan, Greg KH, Andreas Gruenbacher, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 1977 bytes --]

On Thu, Jun 21, 2007 at 09:06:40PM -0400, James Morris wrote:
> On Thu, 21 Jun 2007, Chris Mason wrote:
> 
> > > The incomplete mediation flows from the design, since the pathname-based
> > > mediation doesn't generalize to cover all objects unlike label- or
> > > attribute-based mediation.  And the "use the natural abstraction for
> > > each object type" approach likewise doesn't yield any general model or
> > > anything that you can analyze systematically for data flow.
> > 
> > This feels quite a lot like a repeat of the discussion at the kernel
> > summit.  There are valid uses for path based security, and if they don't
> > fit your needs, please don't use them.  But, path based semantics alone
> > are not a valid reason to shut out AA.
> 
> The validity or otherwise of pathname access control is not being 
> discussed here.
> 
> The point is that the pathname model does not generalize, and that 
> AppArmor's inability to provide adequate coverage of the system is a 
> design issue arising from this.
> 
As we have previously stated we are not using pathnames for IPC.  The
use of pathnames for file access mediation is not a design issue that in
anyway prevents us from extending AppArmor to mediate IPC or networking.

The current focus is making the revision necessary for AppArmor's file
mediation at which point we can focus on finishing of the network
and IPC support.

> Recall that the question asked by Lars was whether there were any 
> outstanding technical issues relating to AppArmor.
> 
> AppArmor does not and can not provide the level of confinement claimed by 
> the documentation, and its policy does not reflect its actual confinement 
> properties.  That's kind of a technical issue, right?
> 
AppArmor currently controls file and capabilities, which was explicitly
stated in the documentation submitted with the patches.  And it has
been posted before that network and IPC mediation are a wip.



[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 20:59                                   ` Stephen Smalley
  2007-06-21 21:17                                     ` Lars Marowsky-Bree
  2007-06-22  0:34                                     ` Chris Mason
@ 2007-06-22  8:06                                     ` John Johansen
  2007-06-22 11:53                                       ` Stephen Smalley
  2007-06-24 20:35                                     ` David Wagner
  3 siblings, 1 reply; 240+ messages in thread
From: John Johansen @ 2007-06-22  8:06 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Lars Marowsky-Bree, James Morris, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 2352 bytes --]

On Thu, Jun 21, 2007 at 04:59:54PM -0400, Stephen Smalley wrote:
> On Thu, 2007-06-21 at 21:54 +0200, Lars Marowsky-Bree wrote:
> > On 2007-06-21T15:42:28, James Morris <jmorris@namei.org> wrote:
> > 
> 
> > And now, yes, I know AA doesn't mediate IPC or networking (yet), but
> > that's a missing feature, not broken by design.
> 
> The incomplete mediation flows from the design, since the pathname-based
> mediation doesn't generalize to cover all objects unlike label- or
> attribute-based mediation.  And the "use the natural abstraction for
> each object type" approach likewise doesn't yield any general model or
> anything that you can analyze systematically for data flow.
> 
No the "incomplete" mediation does not flow from the design.  We have
deliberately focused on doing the necessary modifications for pathname
based mediation.  The IPC and network mediation are a wip.

We have never claimed to be using pathname-based mediation IPC or networking.
The "natural abstraction" approach does generize well enough and will
be analyzable.

> The emphasis on never modifying applications for security in AA likewise
> has an adverse impact here, as you will ultimately have to deal with
> application mediation of access to their own objects and operations not
> directly visible to the kernel (as we have already done in SELinux for
> D-BUS and others and are doing for X).  Otherwise, your "protection" of
> desktop applications is easily subverted.
> 
yes of course, we realize that dbus and X must be trusted applications,
this to will happen.  But it will happen piece meal, something about
releasing early and often comes to mind.

> > > You might define this as a non-technical issue, but the fact that AppArmor 
> > > simply does not and can not work is a fairly significant consideration, I 
> > > would imagine.
> > 
> > If I restrict my Mozilla to not access my on-disk mail folder, it can't
> > get there. (Barring bugs in programs which Mozilla is allowed to run
> > unconfined, sure.)
> 
> Um, no.  It might not be able to directly open files via that path, but
> showing that it can never read or write your mail is a rather different
> matter.
> 
Actually it can be analyzed and shown.  It is ugly to do and we
currently don't have a tool capable of doing it, but it is possible.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-16  0:20                           ` Pavel Machek
@ 2007-06-22  9:59                             ` Andreas Gruenbacher
  0 siblings, 0 replies; 240+ messages in thread
From: Andreas Gruenbacher @ 2007-06-22  9:59 UTC (permalink / raw)
  To: Pavel Machek
  Cc: david, Greg KH, Crispin Cowan, Stephen Smalley, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Saturday 16 June 2007 02:20, Pavel Machek wrote:
> Ok, so mv gets slower for big trees... and open() gets faster for deep
> trees. Previously, open in current directory was one atomic read of
> directory entry, now it has to read directory, and its parent, and its
> parent parent, and its...
>
> (Or am I wrong and getting full path does not need to bring anything
> in, not even in cache-cold case?)

You are wrong, indeed. The dentries in the dcache are connected to the dcache 
through their parent dentry pointers, which means that the parent dentries 
are always in memory, too. No I/O is involved for walking up dentry trees.

(Caveat: nfsd does allow disconnected dentries. It does not make sense to try 
confining an in-kernel daemon though, an no user process can ever access a 
dentry before it gets connected (lookup does that), so this difference is 
irrelevant here.)

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  3:45                                           ` Joshua Brindle
  2007-06-22  5:07                                             ` david
@ 2007-06-22 10:49                                             ` Lars Marowsky-Bree
  1 sibling, 0 replies; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-22 10:49 UTC (permalink / raw)
  To: Joshua Brindle, david
  Cc: Stephen Smalley, James Morris, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On 2007-06-21T23:45:36, Joshua Brindle <method@manicmethod.com> wrote:

> >remember, the policies define a white-list
> 
> Except for unconfined processes.

The argument that AA doesn't mediate what it is not configured to
mediate is correct, yes, but I don't think that's a valid _design_ issue
with AA.

> Or through IPC or the network, that is the point, filesystem only 
> coverage doesn't cut it; there is no way to say the browser can't access 
> the users mail in AA, and there never will be.

We have a variety of filtering mechanisms which are specific to a
domain. iptables filters networking only; file permissions filter file
access only. This argument is not really strong.

<tangent>
If you're now arguing the "spirit of Unix", I can turn your argument
around too: the Unix spirit is to have smallish dedicated tools. If AA
is dedicated to mediating file access, isn't that nice!

AA _could_ be extended to mediate network access and IPC (and this is
WIP). If we had tcpfs and ipcfs - you know, everything is a filesystem,
the Linux spirit! ;-) - AA could mediate them as well.
</tangent>

However, we're discussing the way it mediates file accesses here,
for which it appears useful and capable of functionality which SELinux's
approach cannot provide.


Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 21:17                                     ` Lars Marowsky-Bree
  2007-06-22  0:16                                       ` Joshua Brindle
@ 2007-06-22 11:19                                       ` Stephen Smalley
  2007-06-22 11:34                                         ` Neil Brown
  2007-06-22 11:37                                         ` Lars Marowsky-Bree
  1 sibling, 2 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-22 11:19 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Thu, 2007-06-21 at 23:17 +0200, Lars Marowsky-Bree wrote:
> On 2007-06-21T16:59:54, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> 
> > Or can access the data under a different path to which their profile
> > does give them access, whether in its final destination or in some
> > temporary file processed along the way.
> 
> Well, yes. That is intentional.
> 
> Your point is?

It may very well be unintentional access, especially when taking into
account wildcards in profiles and user-writable directories.

> > The emphasis on never modifying applications for security in AA likewise
> > has an adverse impact here, as you will ultimately have to deal with
> > application mediation of access to their own objects and operations not
> > directly visible to the kernel (as we have already done in SELinux for
> > D-BUS and others and are doing for X).  Otherwise, your "protection" of
> > desktop applications is easily subverted.
> 
> That is an interesting argument, but not what we're discussing here.
> We're arguing filesystem access mediation.

IOW, anything that AA cannot protect against is "out of scope".  An easy
escape from any criticism.

> > Um, no.  It might not be able to directly open files via that path, but
> > showing that it can never read or write your mail is a rather different
> > matter.
> 
> Yes. Your use case is different than mine.

My use case is being able to protect data reliably.  Yours?

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 11:19                                       ` Stephen Smalley
@ 2007-06-22 11:34                                         ` Neil Brown
  2007-06-22 11:48                                           ` Stephen Smalley
  2007-06-22 11:37                                         ` Lars Marowsky-Bree
  1 sibling, 1 reply; 240+ messages in thread
From: Neil Brown @ 2007-06-22 11:34 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Lars Marowsky-Bree, James Morris, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Friday June 22, sds@tycho.nsa.gov wrote:
> > 
> > Yes. Your use case is different than mine.
> 
> My use case is being able to protect data reliably.  Yours?

Saying "protect data" is nearly meaningless without a threat model.
I bet you don't try to protect data from a direct nuclear hit, or a
court order.


AA has a fairly clear threat model.  It involves a flaw in a
program being used by an external agent to cause it to use
privileges it would not normally exercise to subvert privacy or
integrity.
I think this model matches a lot of real threats that real sysadmins
have real concerns about.  I believe that the design of AA addresses
this model quite well. 

What is your threat model?  Maybe it is just different.

NeilBrown

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 11:19                                       ` Stephen Smalley
  2007-06-22 11:34                                         ` Neil Brown
@ 2007-06-22 11:37                                         ` Lars Marowsky-Bree
  2007-06-22 12:41                                           ` Stephen Smalley
  1 sibling, 1 reply; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-22 11:37 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On 2007-06-22T07:19:39, Stephen Smalley <sds@tycho.nsa.gov> wrote:

> > > Or can access the data under a different path to which their profile
> > > does give them access, whether in its final destination or in some
> > > temporary file processed along the way.
> > Well, yes. That is intentional.
> > 
> > Your point is?
> 
> It may very well be unintentional access, especially when taking into
> account wildcards in profiles and user-writable directories.

Again, you're saying that AA is not confining unconfined processes.
That's a given. If unconfined processes assist confined processes in
breeching their confinement, yes, that is not mediated.

You're basically saying that anything but system-wide mandatory access
control is pointless.

If you want to go down that route, what is your reply to me saying that
SELinux cannot mediate NFS mounts - if the server is not confined using
SELinux as well? The argument is really, really moot and pointless. Yes,
unconfined actions can affect confined processes. 

That's generally true for _any_ security system.

> > That is an interesting argument, but not what we're discussing here.
> > We're arguing filesystem access mediation.
> IOW, anything that AA cannot protect against is "out of scope".  An easy
> escape from any criticism.

I'm quite sure that this reply is not AA specific as you try to make it
appear.

> > Yes. Your use case is different than mine.
> My use case is being able to protect data reliably.  Yours?

I want to restrict certain possibly untrusted applications and
network-facing services from accessing certain file patterns, because as
a user and admin, that's the mindset I'm used to. I might be interested
in mediating other channels too, but the files are what I really care
about. I'm inclined to trust the other processes.

Your use case mandates complete system-wide mediation, because you want
full data flow analysis. Mine doesn't.



Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 11:34                                         ` Neil Brown
@ 2007-06-22 11:48                                           ` Stephen Smalley
  0 siblings, 0 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-22 11:48 UTC (permalink / raw)
  To: Neil Brown
  Cc: Lars Marowsky-Bree, James Morris, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 2007-06-22 at 21:34 +1000, Neil Brown wrote:
> On Friday June 22, sds@tycho.nsa.gov wrote:
> > > 
> > > Yes. Your use case is different than mine.
> > 
> > My use case is being able to protect data reliably.  Yours?
> 
> Saying "protect data" is nearly meaningless without a threat model.
> I bet you don't try to protect data from a direct nuclear hit, or a
> court order.
> 
> 
> AA has a fairly clear threat model.  It involves a flaw in a
> program being used by an external agent to cause it to use
> privileges it would not normally exercise to subvert privacy or
> integrity.
> I think this model matches a lot of real threats that real sysadmins
> have real concerns about.  I believe that the design of AA addresses
> this model quite well.
>  
> 
> What is your threat model?  Maybe it is just different.

The threat "model" you describe above is a subset of what SELinux
addresses.  And our argument is that AA does not meet that model well,
because it relies upon ambiguous and unstable identifiers for subjects
and objects (a violation of the fundamental requirements for access
control) and because it provides very incomplete mediation.

>From http://www.nsa.gov/selinux/info/faq.cfm:
The Security-enhanced Linux's new features are designed to enforce the
separation of information based on confidentiality and integrity
requirements. They are designed for preventing processes from reading
data and programs, tampering with data and programs, bypassing
application security mechanisms, executing untrustworthy programs, or
interfering with other processes in violation of the system security
policy. They also help to confine the potential damage that can be
caused by malicious or flawed programs. They should also be useful for
enabling a single system to be used by users with differing security
authorizations to access multiple kinds of information with differing
security requirements without compromising those security requirements.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  8:06                                     ` John Johansen
@ 2007-06-22 11:53                                       ` Stephen Smalley
  2007-06-22 12:42                                         ` Lars Marowsky-Bree
                                                           ` (2 more replies)
  0 siblings, 3 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-22 11:53 UTC (permalink / raw)
  To: John Johansen
  Cc: Lars Marowsky-Bree, James Morris, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 2007-06-22 at 01:06 -0700, John Johansen wrote:
> On Thu, Jun 21, 2007 at 04:59:54PM -0400, Stephen Smalley wrote:
> > On Thu, 2007-06-21 at 21:54 +0200, Lars Marowsky-Bree wrote:
> > > On 2007-06-21T15:42:28, James Morris <jmorris@namei.org> wrote:
> > > 
> > 
> > > And now, yes, I know AA doesn't mediate IPC or networking (yet), but
> > > that's a missing feature, not broken by design.
> > 
> > The incomplete mediation flows from the design, since the pathname-based
> > mediation doesn't generalize to cover all objects unlike label- or
> > attribute-based mediation.  And the "use the natural abstraction for
> > each object type" approach likewise doesn't yield any general model or
> > anything that you can analyze systematically for data flow.
> > 
> No the "incomplete" mediation does not flow from the design.  We have
> deliberately focused on doing the necessary modifications for pathname
> based mediation.  The IPC and network mediation are a wip.

The fact that you have to go back to the drawing board for them is that
you didn't get the abstraction right in the first place.

> We have never claimed to be using pathname-based mediation IPC or networking.
> The "natural abstraction" approach does generize well enough and will
> be analyzable.

I think we must have different understandings of the words "generalize"
and "analyzable".  Look, if I want to be able to state properties about
data flow in the system for confidentiality or integrity goals (my
secret data can never leak to unauthorized entities, my critical data
can never be corrupted/tainted by unauthorized entities - directly or
indirectly), then I need to be able to have a common reference point for
my policy.  When my policy is based on different abstractions
(pathnames, IP addresses, window ids, whatever) for different objects,
then I can no longer identify how data can flow throughout the system in
a system-wide way. 

> > Um, no.  It might not be able to directly open files via that path, but
> > showing that it can never read or write your mail is a rather different
> > matter.
> > 
> Actually it can be analyzed and shown.  It is ugly to do and we
> currently don't have a tool capable of doing it, but it is possible.

No, it isn't possible when using ambiguous and unstable identifiers for
the subjects and objects, nor when mediation is incomplete.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  1:06                                       ` James Morris
  2007-06-22  4:17                                         ` Crispin Cowan
  2007-06-22  7:40                                         ` John Johansen
@ 2007-06-22 12:17                                         ` Chris Mason
  2007-06-22 13:48                                           ` James Morris
  2007-06-24 21:20                                         ` David Wagner
  3 siblings, 1 reply; 240+ messages in thread
From: Chris Mason @ 2007-06-22 12:17 UTC (permalink / raw)
  To: James Morris
  Cc: Stephen Smalley, Lars Marowsky-Bree, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Thu, Jun 21, 2007 at 09:06:40PM -0400, James Morris wrote:
> On Thu, 21 Jun 2007, Chris Mason wrote:
> 
> > > The incomplete mediation flows from the design, since the pathname-based
> > > mediation doesn't generalize to cover all objects unlike label- or
> > > attribute-based mediation.  And the "use the natural abstraction for
> > > each object type" approach likewise doesn't yield any general model or
> > > anything that you can analyze systematically for data flow.
> > 
> > This feels quite a lot like a repeat of the discussion at the kernel
> > summit.  There are valid uses for path based security, and if they don't
> > fit your needs, please don't use them.  But, path based semantics alone
> > are not a valid reason to shut out AA.
> 
> The validity or otherwise of pathname access control is not being 
> discussed here.
> 
> The point is that the pathname model does not generalize, and that 
> AppArmor's inability to provide adequate coverage of the system is a 
> design issue arising from this.

I'm sorry, but I don't see where in the paragraphs above you aren't
making a general argument against the pathname model.

-chris


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  4:17                                         ` Crispin Cowan
@ 2007-06-22 12:20                                           ` Stephen Smalley
  2007-06-24 20:45                                             ` David Wagner
  0 siblings, 1 reply; 240+ messages in thread
From: Stephen Smalley @ 2007-06-22 12:20 UTC (permalink / raw)
  To: Crispin Cowan
  Cc: James Morris, Chris Mason, Lars Marowsky-Bree, Pavel Machek,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Thu, 2007-06-21 at 22:17 -0600, Crispin Cowan wrote:
> James Morris wrote:
> > On Thu, 21 Jun 2007, Chris Mason wrote:  
> >>> The incomplete mediation flows from the design, since the pathname-based
> >>> mediation doesn't generalize to cover all objects unlike label- or
> >>> attribute-based mediation.  And the "use the natural abstraction for
> >>> each object type" approach likewise doesn't yield any general model or
> >>> anything that you can analyze systematically for data flow.
> >>>       
> >> This feels quite a lot like a repeat of the discussion at the kernel
> >> summit.  There are valid uses for path based security, and if they don't
> >> fit your needs, please don't use them.  But, path based semantics alone
> >> are not a valid reason to shut out AA.
> >>     
> > The validity or otherwise of pathname access control is not being 
> > discussed here.
> >
> > The point is that the pathname model does not generalize, and that 
> > AppArmor's inability to provide adequate coverage of the system is a 
> > design issue arising from this.
> >   
> The above two paragraphs appear to contradict each other.
> 
> > Recall that the question asked by Lars was whether there were any 
> > outstanding technical issues relating to AppArmor.
> >
> > AppArmor does not and can not provide the level of confinement claimed by 
> > the documentation, and its policy does not reflect its actual confinement 
> > properties.  That's kind of a technical issue, right?
> >   
> So if the document said "confinement with respect to direct file access
> and POSIX.1e capabilities" and that list got extended as AA got new
> confinement features, would that address your issue?

That would certainly help, although one might quibble with the use of
the word "confinement" at all wrt AppArmor (it has a long-established
technical meaning that implies information flow control, and that goes
beyond even complete mediation - it requires global and persistent
protection of the data based on its properties, which requires stable
and unambiguous identifiers).

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 11:37                                         ` Lars Marowsky-Bree
@ 2007-06-22 12:41                                           ` Stephen Smalley
  2007-06-22 12:54                                             ` Lars Marowsky-Bree
  2007-06-22 16:06                                             ` Casey Schaufler
  0 siblings, 2 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-22 12:41 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 2007-06-22 at 13:37 +0200, Lars Marowsky-Bree wrote:
> On 2007-06-22T07:19:39, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> 
> > > > Or can access the data under a different path to which their profile
> > > > does give them access, whether in its final destination or in some
> > > > temporary file processed along the way.
> > > Well, yes. That is intentional.
> > > 
> > > Your point is?
> > 
> > It may very well be unintentional access, especially when taking into
> > account wildcards in profiles and user-writable directories.
> 
> Again, you're saying that AA is not confining unconfined processes.
> That's a given. If unconfined processes assist confined processes in
> breeching their confinement, yes, that is not mediated.

The issue arises even for a collection of collaborating confined
processes with different profiles, and the collaboration may be
intentional or unintentional (in the latter case, one of the confined
processes may be taking advantage of known behavior of another process
and shared access by both to some resource in order to induce a
particular behavior in that process).

And remember that confinement isn't just about limiting untrusted
processes but also about protecting trusted processes; limiting the
inputs and outputs of a trusted process can be just as important to
preventing exploitation.

> You're basically saying that anything but system-wide mandatory access
> control is pointless.

Mandatory access control as historically understood has always meant
system-wide.  As well as always being based on the security properties
of the data (so that global and persistent protection of the data is
possible).  You can't actually use the terms 'mandatory access control'
or 'confinement' for AppArmor unless you redefine them.

> If you want to go down that route, what is your reply to me saying that
> SELinux cannot mediate NFS mounts - if the server is not confined using
> SELinux as well? The argument is really, really moot and pointless. Yes,
> unconfined actions can affect confined processes. 

Sorry, do you mean the "server" as in the "server system" or as in the
"server daemon"?  For the former, I'd agree - we would want SELinux
policy applied on the server as well as the client to ensure that the
data is being protected consistently throughout and that the server is
not misrepresenting the security guarantees expected by the clients.
Providing an illusion of confinement on each client without any
corresponding protection on the server system would be very prone to
bypass.  For the latter, the kernel can only truly confine application
code, not in-kernel threads, although we can subject the in-kernel nfsd
to permission checking as a robustness check.  We've always noted that
SELinux does depend on the correctness of the kernel.

> > > That is an interesting argument, but not what we're discussing here.
> > > We're arguing filesystem access mediation.
> > IOW, anything that AA cannot protect against is "out of scope".  An easy
> > escape from any criticism.
> 
> I'm quite sure that this reply is not AA specific as you try to make it
> appear.

Every time we've noted an issue with AA, the answer has been that it is
out of scope.  Yet the public documentation for AA misrepresents the
situation and its comparisons with SELinux conveniently ignore its
limitations.

> > > Yes. Your use case is different than mine.
> > My use case is being able to protect data reliably.  Yours?
> 
> I want to restrict certain possibly untrusted applications and
> network-facing services from accessing certain file patterns, because as
> a user and admin, that's the mindset I'm used to. I might be interested
> in mediating other channels too, but the files are what I really care
> about. I'm inclined to trust the other processes.
> 
> Your use case mandates complete system-wide mediation, because you want
> full data flow analysis. Mine doesn't.

Then yours isn't mandatory access control, nor is it confinement.  

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 11:53                                       ` Stephen Smalley
@ 2007-06-22 12:42                                         ` Lars Marowsky-Bree
  2007-06-22 12:46                                           ` Stephen Smalley
  2007-06-22 18:35                                         ` david
  2007-06-24 20:48                                         ` David Wagner
  2 siblings, 1 reply; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-22 12:42 UTC (permalink / raw)
  To: Stephen Smalley, John Johansen
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, linux-kernel, linux-security-module,
	linux-fsdevel

On 2007-06-22T07:53:47, Stephen Smalley <sds@tycho.nsa.gov> wrote:

> > No the "incomplete" mediation does not flow from the design.  We have
> > deliberately focused on doing the necessary modifications for pathname
> > based mediation.  The IPC and network mediation are a wip.
> The fact that you have to go back to the drawing board for them is that
> you didn't get the abstraction right in the first place.

That's an interesting claim, however I don't think it holds. AA was
designed to mediate file access in a form which is intuitive to admins.

It's to be expected that it doesn't directly apply to mediating other
forms of access.

> I think we must have different understandings of the words "generalize"
> and "analyzable".  Look, if I want to be able to state properties about
> data flow in the system for confidentiality or integrity goals (my
> secret data can never leak to unauthorized entities, my critical data
> can never be corrupted/tainted by unauthorized entities - directly or
> indirectly),

I seem to think that this is not what AA is trying to do, so evaluating
it in that context doesn't seem useful. It's like saying a screw driver
isn't a hammer, so it is useless because you have a nail.


Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 12:42                                         ` Lars Marowsky-Bree
@ 2007-06-22 12:46                                           ` Stephen Smalley
  0 siblings, 0 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-22 12:46 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: John Johansen, James Morris, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 2007-06-22 at 14:42 +0200, Lars Marowsky-Bree wrote:
> On 2007-06-22T07:53:47, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> 
> > > No the "incomplete" mediation does not flow from the design.  We have
> > > deliberately focused on doing the necessary modifications for pathname
> > > based mediation.  The IPC and network mediation are a wip.
> > The fact that you have to go back to the drawing board for them is that
> > you didn't get the abstraction right in the first place.
> 
> That's an interesting claim, however I don't think it holds. AA was
> designed to mediate file access in a form which is intuitive to admins.
> 
> It's to be expected that it doesn't directly apply to mediating other
> forms of access.
> 
> > I think we must have different understandings of the words "generalize"
> > and "analyzable".  Look, if I want to be able to state properties about
> > data flow in the system for confidentiality or integrity goals (my
> > secret data can never leak to unauthorized entities, my critical data
> > can never be corrupted/tainted by unauthorized entities - directly or
> > indirectly),
> 
> I seem to think that this is not what AA is trying to do, so evaluating
> it in that context doesn't seem useful. It's like saying a screw driver
> isn't a hammer, so it is useless because you have a nail.

Again, in that case, please remove all uses of the terms "mandatory
access control", "confinement" and "integrity protection" from AA
documentation and code.

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 12:41                                           ` Stephen Smalley
@ 2007-06-22 12:54                                             ` Lars Marowsky-Bree
  2007-06-22 13:22                                               ` Stephen Smalley
  2007-06-22 16:06                                             ` Casey Schaufler
  1 sibling, 1 reply; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-22 12:54 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On 2007-06-22T08:41:51, Stephen Smalley <sds@tycho.nsa.gov> wrote:

> The issue arises even for a collection of collaborating confined
> processes with different profiles, and the collaboration may be
> intentional or unintentional (in the latter case, one of the confined
> processes may be taking advantage of known behavior of another process
> and shared access by both to some resource in order to induce a
> particular behavior in that process).

Point taken; the point remains is that you need at least several
(intentionally or not) cooperating processes. The chances of this are
significantly lower than a single process exploit.

> And remember that confinement isn't just about limiting untrusted
> processes but also about protecting trusted processes; limiting the
> inputs and outputs of a trusted process can be just as important to
> preventing exploitation.

True. It'd appear that if you want that, you'd specify the AA profile so
that it doesn't include directories/files writable by untrusted
processes.

> Sorry, do you mean the "server" as in the "server system" or as in the
> "server daemon"?  For the former, I'd agree - we would want SELinux
> policy applied on the server as well as the client to ensure that the
> data is being protected consistently throughout and that the server is
> not misrepresenting the security guarantees expected by the clients.
> Providing an illusion of confinement on each client without any
> corresponding protection on the server system would be very prone to
> bypass.  For the latter, the kernel can only truly confine application
> code, not in-kernel threads, although we can subject the in-kernel nfsd
> to permission checking as a robustness check.  We've always noted that
> SELinux does depend on the correctness of the kernel.

Oh, you're saying that this threat is out-of-scope? ;-)

> Every time we've noted an issue with AA, the answer has been that it is
> out of scope.  Yet the public documentation for AA misrepresents the
> situation and its comparisons with SELinux conveniently ignore its
> limitations.

I'm sorry. Again, I'm not responsible for marketing comparisons made by
anyone else, nor do I think they should apply to this discussion where
we're discussing the merits of what AA actually _does_; not what
someone's marketing claims it does - otherwise I'll go dig out marketing
claims about SELinux too ;-)

And, coming at it from that direction, I feel it does something useful.

Note that here we've already strayed from the focus of the discussion;
we're no longer arguing "the implementation is ugly/broken", but you're
claiming "doesn't do what I need" - which I'm not disagreeing with. It
doesn't do what you want. Which is why you have SELinux, and it's going
to stay. Fine.

If we assume that the users who run it do have a need / use case for it
which they can't solve differently, we should really get back to the
discussion of how those needs can be met or provided by Linux in a
feasible way.

> > Your use case mandates complete system-wide mediation, because you want
> > full data flow analysis. Mine doesn't.
> Then yours isn't mandatory access control, nor is it confinement.  

I apologize for not using the word "confinement" in the way you expect
it to be used. I certainly don't want to imply it does do things it
doesn't. Keep in mind I'm not a native speaker, so nuances do get lost
sometimes; nor do I have long years of experience in the security
field. Thanks for clearing this up.

So agreed, it is not confinement nor MAC.

Would it be more appropriate if I used the word "restricts" or
"constrains"?


Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 12:54                                             ` Lars Marowsky-Bree
@ 2007-06-22 13:22                                               ` Stephen Smalley
  2007-06-22 14:49                                                 ` Stephen Smalley
  0 siblings, 1 reply; 240+ messages in thread
From: Stephen Smalley @ 2007-06-22 13:22 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 2007-06-22 at 14:54 +0200, Lars Marowsky-Bree wrote:
> On 2007-06-22T08:41:51, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> > Sorry, do you mean the "server" as in the "server system" or as in the
> > "server daemon"?  For the former, I'd agree - we would want SELinux
> > policy applied on the server as well as the client to ensure that the
> > data is being protected consistently throughout and that the server is
> > not misrepresenting the security guarantees expected by the clients.
> > Providing an illusion of confinement on each client without any
> > corresponding protection on the server system would be very prone to
> > bypass.  For the latter, the kernel can only truly confine application
> > code, not in-kernel threads, although we can subject the in-kernel nfsd
> > to permission checking as a robustness check.  We've always noted that
> > SELinux does depend on the correctness of the kernel.
> 
> Oh, you're saying that this threat is out-of-scope? ;-)

Kernel flaws aren't something we can address (reliably and in general)
via a kernel mechanism.  Versus a threat that can be addressed by kernel
mechanism, like providing complete mediation and unambiguous access
control.  There is a difference.  And we aren't ignoring the kernel
correctness problem - there is separate work in that space, but it
requires separate mechanism outside of SELinux itself.

> Note that here we've already strayed from the focus of the discussion;
> we're no longer arguing "the implementation is ugly/broken", but you're
> claiming "doesn't do what I need" - which I'm not disagreeing with. It
> doesn't do what you want. Which is why you have SELinux, and it's going
> to stay. Fine.
> 
> If we assume that the users who run it do have a need / use case for it
> which they can't solve differently, we should really get back to the
> discussion of how those needs can be met or provided by Linux in a
> feasible way.

Part of the discussion has been whether those users' needs could be
solved better via SELinux, whether via improved userspace tools (ala
seedit possibly with an enhanced restorecond) or via extended kernel
mechanism (ala named type transitions and some kind of inheritance
model).  It does however seem like there is a fundamental conflict there
on renaming behavior; I do not believe that file protections should
automatically change in the kernel upon rename and should require
explicit userspace action.  The question though is whether that renaming
behavior in AA is truly a user requirement or a manufactured (i.e.
made-up) one, and whether it is truly a runtime requirement or just a
policy creation time one (the latter being adequately addressed by
userspace relabeling).

If that behavior is truly needed (a point I wouldn't concede), then the
discussion does reduce down to the right implementation method.  There
it appears that the primary objection is to regenerating full pathname
strings and matching them versus some kind of incremental matching
either during lookup itself or via a reverse match as suggested.  That
discussion is principally one in which the vfs folks should be engaged,
not me.

> > > Your use case mandates complete system-wide mediation, because you want
> > > full data flow analysis. Mine doesn't.
> > Then yours isn't mandatory access control, nor is it confinement.  
> 
> I apologize for not using the word "confinement" in the way you expect
> it to be used. I certainly don't want to imply it does do things it
> doesn't. Keep in mind I'm not a native speaker, so nuances do get lost
> sometimes; nor do I have long years of experience in the security
> field. Thanks for clearing this up.
> 
> So agreed, it is not confinement nor MAC.
> 
> Would it be more appropriate if I used the word "restricts" or
> "constrains"?

Yes.  Or simply "controls file accesses and capability usage".

-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 12:17                                         ` Chris Mason
@ 2007-06-22 13:48                                           ` James Morris
  2007-06-22 14:02                                             ` Chris Mason
                                                               ` (2 more replies)
  0 siblings, 3 replies; 240+ messages in thread
From: James Morris @ 2007-06-22 13:48 UTC (permalink / raw)
  To: Chris Mason
  Cc: Stephen Smalley, Lars Marowsky-Bree, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 22 Jun 2007, Chris Mason wrote:

> > The validity or otherwise of pathname access control is not being 
> > discussed here.
> > 
> > The point is that the pathname model does not generalize, and that 
> > AppArmor's inability to provide adequate coverage of the system is a 
> > design issue arising from this.
> 
> I'm sorry, but I don't see where in the paragraphs above you aren't
> making a general argument against the pathname model.

There are two distinct concepts here.

A. Pathname labeling - applying access control to pathnames to objects, 
rather than labeling the objects themselves.

Think of this as, say, securing your house by putting a gate in the street 
in front of the house, regardless of how many other possible paths there 
are to the house via other streets, adjoining properties etc.

Pathname labeling and mediation is simply mediating a well-known path to 
the object.  In this analogy, object labeling would instead ensure that 
all of the accessible doors, windows and other entrances of the house were 
locked, so that someone trying to break in from the rear alley would 
not get in simply by bypassing the front gate and opening any door.

What you do with AppArmor, instead of addressing the problem, is just 
redefine the environment along the lines of "set your house into a rock 
wall so there is only one path to it".


B. Pathname access control as a general abstraction for OS security.

Which is what was being discussed above, in response to a question from 
Lars about technical issues, and that this _model_ doesn't generalize to 
the rest of the OS, regardless of whether you think the mechanism of 
pathname labeling itself is appropriate or not.

In any case, clarifying such a distinction should not obscure the central 
issue, which is: AppArmor's design is broken.

General users, many kernel developers, and even security researchers who 
have not yet looked under the covers [1], are probably unaware that the 
confinement claims being made about AppArmor's confinement capabilities 
are simply not possible with either its model or implementation.

To quote from:

http://www.novell.com/linux/security/apparmor/

  "AppArmor gives you network application security via mandatory access 
   control for programs, protecting against the exploitation of software 
   flaws and compromised systems. AppArmor includes everything you need to 
   provide effective containment for programs (including those that run as 
   root) to thwart attempted exploits and even zero-day attacks."

This is not accurate in any sense of the term containment of mandatory 
access control that I've previously encountered.

The fact that it doesn't work as expected does not arise simply from 
missing features or being "different".  It arises from the design of the 
system, which uses a pathname abstraction, where, even if we agree to 
ignore issue (1) above, still does not work, because only filesystem 
interactions are mediated.

AppArmor policy does not reflect the behavior of the system.

The "simple" policy that users can so effortlessly manipulate is simple 
because it is wrong, and deliberately so.

The design of the AppArmor is based on _appearing simple_, but at the 
expense of completeness and thus correctness.


[1] http://lkml.org/lkml/2007/4/19/357

  "My gosh, you're right.  What the heck?  With all due respect to the
   developers of AppArmor, I can't help thinking that that's pretty lame.
   I think this raises substantial questions about the value of AppArmor.
   What is the point of having a jail if it leaves gaping holes that
   malicious code could use to escape?

   And why isn't this documented clearly, with the implications fully
   explained?"  - David Wagner, http://www.cs.berkeley.edu/~daw/
     

Indeed.



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 13:48                                           ` James Morris
@ 2007-06-22 14:02                                             ` Chris Mason
  2007-06-22 14:23                                               ` James Morris
  2007-06-25 15:14                                               ` Pavel Machek
  2007-06-24 21:16                                             ` David Wagner
  2007-06-24 21:45                                             ` David Wagner
  2 siblings, 2 replies; 240+ messages in thread
From: Chris Mason @ 2007-06-22 14:02 UTC (permalink / raw)
  To: James Morris
  Cc: Stephen Smalley, Lars Marowsky-Bree, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, Jun 22, 2007 at 09:48:12AM -0400, James Morris wrote:
> On Fri, 22 Jun 2007, Chris Mason wrote:
> 
> > > The validity or otherwise of pathname access control is not being 
> > > discussed here.
> > > 
> > > The point is that the pathname model does not generalize, and that 
> > > AppArmor's inability to provide adequate coverage of the system is a 
> > > design issue arising from this.
> > 
> > I'm sorry, but I don't see where in the paragraphs above you aren't
> > making a general argument against the pathname model.
> 
> There are two distinct concepts here.
> 
> A. Pathname labeling - applying access control to pathnames to objects, 
> rather than labeling the objects themselves.
> 
> Think of this as, say, securing your house by putting a gate in the street 
> in front of the house, regardless of how many other possible paths there 
> are to the house via other streets, adjoining properties etc.
> 
> Pathname labeling and mediation is simply mediating a well-known path to 
> the object.  In this analogy, object labeling would instead ensure that 
> all of the accessible doors, windows and other entrances of the house were 
> locked, so that someone trying to break in from the rear alley would 
> not get in simply by bypassing the front gate and opening any door.
> 
> What you do with AppArmor, instead of addressing the problem, is just 
> redefine the environment along the lines of "set your house into a rock 
> wall so there is only one path to it".
> 
> 
> B. Pathname access control as a general abstraction for OS security.
> 
> Which is what was being discussed above, in response to a question from 
> Lars about technical issues, and that this _model_ doesn't generalize to 
> the rest of the OS, regardless of whether you think the mechanism of 
> pathname labeling itself is appropriate or not.

I'm sorry, but I don't see where in the paragraphs above you aren't
making a general argument against the pathname model.  I'm not trying to
get into that discussion (I'm smart enough to know I'm far too stupid to
hold my own there).

I do understand that AA is different from selinux, and that you
have valid points about the level and type of protection that AA offers.

But, this is a completely different discussion than if AA is
solving problems in the wild for its intended audience, or if the code
is somehow flawed and breaking other parts of the kernel.

We've been over the "AA is different" discussion in threads about a
billion times, and at the last kernel summit.  I think Lars and others
have done a pretty good job of describing the problems they are trying
to solve, can we please move on to discussing technical issues around
that?

-chris




^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 14:02                                             ` Chris Mason
@ 2007-06-22 14:23                                               ` James Morris
  2007-06-22 17:30                                                 ` Chris Mason
  2007-06-22 18:12                                                 ` david
  2007-06-25 15:14                                               ` Pavel Machek
  1 sibling, 2 replies; 240+ messages in thread
From: James Morris @ 2007-06-22 14:23 UTC (permalink / raw)
  To: Chris Mason
  Cc: Stephen Smalley, Lars Marowsky-Bree, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 22 Jun 2007, Chris Mason wrote:

> But, this is a completely different discussion than if AA is
> solving problems in the wild for its intended audience, or if the code
> is somehow flawed and breaking other parts of the kernel.

Is its intended audience aware of its limitiations?  Lars has just 
acknowledged that it does not implement mandatory access control, for one.

Until people understand these issues, they certainly need to be addressed 
in the context of upstream merge.

> We've been over the "AA is different" discussion in threads about a
> billion times, and at the last kernel summit.

I don't believe that people at the summit were adequately informed on the 
issue, and from several accounts I've heard, Stephen Smalley was 
effectively cut off before he could even get to his second slide.

> I think Lars and others have done a pretty good job of describing the 
> problems they are trying to solve, can we please move on to discussing 
> technical issues around that?

Keep in mind that this current thread arose from Greg KH asking about 
whether AppArmor could effectively be implemented via SELinux and 
userspace labeling.

Some of us took the time to perform analysis and then provide feedback on 
this, in good faith.

The underlying issues only came up again in response to an inflammatory 
post by Lars.  If you want to avoid discussions of AppArmor's design, then 
I suggest taking it up with those who initiate them.



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 13:22                                               ` Stephen Smalley
@ 2007-06-22 14:49                                                 ` Stephen Smalley
  0 siblings, 0 replies; 240+ messages in thread
From: Stephen Smalley @ 2007-06-22 14:49 UTC (permalink / raw)
  To: Lars Marowsky-Bree
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 2007-06-22 at 09:22 -0400, Stephen Smalley wrote:
> On Fri, 2007-06-22 at 14:54 +0200, Lars Marowsky-Bree wrote:
> > On 2007-06-22T08:41:51, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> > > Sorry, do you mean the "server" as in the "server system" or as in the
> > > "server daemon"?  For the former, I'd agree - we would want SELinux
> > > policy applied on the server as well as the client to ensure that the
> > > data is being protected consistently throughout and that the server is
> > > not misrepresenting the security guarantees expected by the clients.
> > > Providing an illusion of confinement on each client without any
> > > corresponding protection on the server system would be very prone to
> > > bypass.  For the latter, the kernel can only truly confine application
> > > code, not in-kernel threads, although we can subject the in-kernel nfsd
> > > to permission checking as a robustness check.  We've always noted that
> > > SELinux does depend on the correctness of the kernel.
> > 
> > Oh, you're saying that this threat is out-of-scope? ;-)
> 
> Kernel flaws aren't something we can address (reliably and in general)
> via a kernel mechanism.  Versus a threat that can be addressed by kernel
> mechanism, like providing complete mediation and unambiguous access
> control.  There is a difference.  And we aren't ignoring the kernel
> correctness problem - there is separate work in that space, but it
> requires separate mechanism outside of SELinux itself.
> 
> > Note that here we've already strayed from the focus of the discussion;
> > we're no longer arguing "the implementation is ugly/broken", but you're
> > claiming "doesn't do what I need" - which I'm not disagreeing with. It
> > doesn't do what you want. Which is why you have SELinux, and it's going
> > to stay. Fine.
> > 
> > If we assume that the users who run it do have a need / use case for it
> > which they can't solve differently, we should really get back to the
> > discussion of how those needs can be met or provided by Linux in a
> > feasible way.
> 
> Part of the discussion has been whether those users' needs could be
> solved better via SELinux, whether via improved userspace tools (ala
> seedit possibly with an enhanced restorecond) or via extended kernel
> mechanism (ala named type transitions and some kind of inheritance
> model).  It does however seem like there is a fundamental conflict there
> on renaming behavior; I do not believe that file protections should
> automatically change in the kernel upon rename and should require
> explicit userspace action.  The question though is whether that renaming
> behavior in AA is truly a user requirement or a manufactured (i.e.
> made-up) one, and whether it is truly a runtime requirement or just a
> policy creation time one (the latter being adequately addressed by
> userspace relabeling).

I suppose there is also a question of whether that kind of model
wouldn't be better implemented as an ACL model with implicit
inheritance, e.g. if you specify an ACL on a directory, then all files
accessed via that directory are controlled in accordance with that ACL
unless they have their own more specific ACL, and if you move one of
those files to a different directory, then they automatically pick up
the protection of the new parent.  Doesn't require the kernel to be
matching pathname strings, just walking up the tree to determine the
closest ancestor with an explicit ACL on it.

> 
> If that behavior is truly needed (a point I wouldn't concede), then the
> discussion does reduce down to the right implementation method.  There
> it appears that the primary objection is to regenerating full pathname
> strings and matching them versus some kind of incremental matching
> either during lookup itself or via a reverse match as suggested.  That
> discussion is principally one in which the vfs folks should be engaged,
> not me.
> 
> > > > Your use case mandates complete system-wide mediation, because you want
> > > > full data flow analysis. Mine doesn't.
> > > Then yours isn't mandatory access control, nor is it confinement.  
> > 
> > I apologize for not using the word "confinement" in the way you expect
> > it to be used. I certainly don't want to imply it does do things it
> > doesn't. Keep in mind I'm not a native speaker, so nuances do get lost
> > sometimes; nor do I have long years of experience in the security
> > field. Thanks for clearing this up.
> > 
> > So agreed, it is not confinement nor MAC.
> > 
> > Would it be more appropriate if I used the word "restricts" or
> > "constrains"?
> 
> Yes.  Or simply "controls file accesses and capability usage".
> 
-- 
Stephen Smalley
National Security Agency


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 12:41                                           ` Stephen Smalley
  2007-06-22 12:54                                             ` Lars Marowsky-Bree
@ 2007-06-22 16:06                                             ` Casey Schaufler
  1 sibling, 0 replies; 240+ messages in thread
From: Casey Schaufler @ 2007-06-22 16:06 UTC (permalink / raw)
  To: Stephen Smalley, Lars Marowsky-Bree
  Cc: James Morris, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel


--- Stephen Smalley <sds@tycho.nsa.gov> wrote:

 
> Mandatory access control as historically understood has always meant
> system-wide.

Chapter and verse: TCSEC 3.1.1.4 Mandatory Access Control
  "The TCB shall enforce a mandatory access control policy over
   all subjects and storage objects under its control."

Chapter and verse: TCSEC 3.2.1.4 Mandatory Access Control
  "The TCB shall enforce a mandatory access control policy over
   all resources that are directly or indirectly accessible by
   subjects external to the TCB."

The first reference is in the definition of a B1 system, while the
second is for a B2 system. It was made clear to those of us
doing TCSEC evaluations that there is a very real distintion between
these two requirements. In the history that I've been through,
starting in 1987, the B1 requirement has been read to allow for
things that are not storage objects to be uncontrolled while the
B2 requirement does not. If everything is a storage object, which
is the approach everybody took, yes, you're looking at system wide.
If, on the other hand, you were to take a different model approach
and say that networking does not use storage objects you would not
have to account for them under the B1 rules, while you would still
have to for B2. Historically, no one succeeded with B2, and the
mindset of B1 prevailed. So, historically, the understanding was
that it was easier to declare everything a storage object and code
up some MAC for it than it was to provide a security model that
explained networking as it really works. I suggest that if AA wants
to declare that as far as they are concerned sockets, ports, and
packets are none of them storage objects but are instead pregnant
weasels that is their peragotive as system designers and that
a B1 evaluation team would have accepted that, provided sufficient
evidence and explaination of the relevence of pregnant weasels
was provided. It would not have worked at B2, but historically
everyone understood that B2 was out of reach.

Stephen is correct in that historically everyone implemented system
that put everything under MAC, but is not in that it was well
understood that if you could define something as not being a
storage object you didn't have to submit it to MAC. Then as now
it was easier to get people to code MAC than to get them to write
papers about the security properties of pregnant weasels.



Casey Schaufler
casey@schaufler-ca.com

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 14:23                                               ` James Morris
@ 2007-06-22 17:30                                                 ` Chris Mason
  2007-06-23  0:11                                                   ` Chris Wright
  2007-06-24 20:43                                                   ` Pavel Machek
  2007-06-22 18:12                                                 ` david
  1 sibling, 2 replies; 240+ messages in thread
From: Chris Mason @ 2007-06-22 17:30 UTC (permalink / raw)
  To: James Morris
  Cc: Stephen Smalley, Lars Marowsky-Bree, Pavel Machek, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, Jun 22, 2007 at 10:23:03AM -0400, James Morris wrote:
> On Fri, 22 Jun 2007, Chris Mason wrote:
> 
> > But, this is a completely different discussion than if AA is
> > solving problems in the wild for its intended audience, or if the code
> > is somehow flawed and breaking other parts of the kernel.
> 
> Is its intended audience aware of its limitiations?  Lars has just 
> acknowledged that it does not implement mandatory access control, for one.
> 
> Until people understand these issues, they certainly need to be addressed 
> in the context of upstream merge.

It is definitely useful to clearly understand the intended AA use cases
during the merge.

> 
> > We've been over the "AA is different" discussion in threads about a
> > billion times, and at the last kernel summit.
> 
> I don't believe that people at the summit were adequately informed on the 
> issue, and from several accounts I've heard, Stephen Smalley was 
> effectively cut off before he could even get to his second slide.

I'm sure people there will have a different versions of events.  The
one part that was discussed was if pathname based security was
useful, and a number of the people in the room (outside of 
novell) said it was.  Now, it could be that nobody wanted to argue
anymore, since most opinions had come out on one list or another by
then.  

But as someone who doesn't use either SElinux or AA, I really hope
we can get past the part of the debate where:

while(1)
    AA) we think we're making users happy with pathname security
    SELINUX) pathname security sucks

So, yes Greg got it started and Lars is a well known trouble maker, and
I completely understand if you want to say no thank you to an selinux
based AA ;)  The models are different and it shouldn't be a requirement
that they try to use the same underlying mechanisms.

-chris


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 14:23                                               ` James Morris
  2007-06-22 17:30                                                 ` Chris Mason
@ 2007-06-22 18:12                                                 ` david
  1 sibling, 0 replies; 240+ messages in thread
From: david @ 2007-06-22 18:12 UTC (permalink / raw)
  To: James Morris
  Cc: Chris Mason, Stephen Smalley, Lars Marowsky-Bree, Pavel Machek,
	Crispin Cowan, Greg KH, Andreas Gruenbacher, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Fri, 22 Jun 2007, James Morris wrote:

> On Fri, 22 Jun 2007, Chris Mason wrote:
>
>> But, this is a completely different discussion than if AA is
>> solving problems in the wild for its intended audience, or if the code
>> is somehow flawed and breaking other parts of the kernel.
>
> Is its intended audience aware of its limitiations?  Lars has just
> acknowledged that it does not implement mandatory access control, for one.
>
> Until people understand these issues, they certainly need to be addressed
> in the context of upstream merge.

there are always going to be people who misunderstand things. by this 
logic nothing can ever be merged that can be misused.

at least some of the intended audience (including me) do understand the 
limits and still consider the result useful.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 11:53                                       ` Stephen Smalley
  2007-06-22 12:42                                         ` Lars Marowsky-Bree
@ 2007-06-22 18:35                                         ` david
  2007-06-24 20:48                                         ` David Wagner
  2 siblings, 0 replies; 240+ messages in thread
From: david @ 2007-06-22 18:35 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: John Johansen, Lars Marowsky-Bree, James Morris, Pavel Machek,
	Crispin Cowan, Greg KH, Andreas Gruenbacher, linux-kernel,
	linux-security-module, linux-fsdevel

On Fri, 22 Jun 2007, Stephen Smalley wrote:

> On Fri, 2007-06-22 at 01:06 -0700, John Johansen wrote:
>> On Thu, Jun 21, 2007 at 04:59:54PM -0400, Stephen Smalley wrote:
>>> On Thu, 2007-06-21 at 21:54 +0200, Lars Marowsky-Bree wrote:
>>>> On 2007-06-21T15:42:28, James Morris <jmorris@namei.org> wrote:
>>>>
>>>
>>>> And now, yes, I know AA doesn't mediate IPC or networking (yet), but
>>>> that's a missing feature, not broken by design.
>>>
>>> The incomplete mediation flows from the design, since the pathname-based
>>> mediation doesn't generalize to cover all objects unlike label- or
>>> attribute-based mediation.  And the "use the natural abstraction for
>>> each object type" approach likewise doesn't yield any general model or
>>> anything that you can analyze systematically for data flow.
>>>
>> No the "incomplete" mediation does not flow from the design.  We have
>> deliberately focused on doing the necessary modifications for pathname
>> based mediation.  The IPC and network mediation are a wip.
>
> The fact that you have to go back to the drawing board for them is that
> you didn't get the abstraction right in the first place.

or it just means that the tool to regulat the network is different from 
the tool to regulate the filesystem.

oh, by the way. that's how the rest of the *nix world works. firewall 
rules apply to networking, filesystem permissions and ACLs apply to the 
filesystem.

this is like climing that the latest improvement to ipsec shouldn't go in 
becouse it down't allow you to handle things the same way that you handle 
temp files or a serial port.

>> We have never claimed to be using pathname-based mediation IPC or networking.
>> The "natural abstraction" approach does generize well enough and will
>> be analyzable.
>
> I think we must have different understandings of the words "generalize"
> and "analyzable".  Look, if I want to be able to state properties about
> data flow in the system for confidentiality or integrity goals (my
> secret data can never leak to unauthorized entities, my critical data
> can never be corrupted/tainted by unauthorized entities - directly or
> indirectly), then I need to be able to have a common reference point for
> my policy.  When my policy is based on different abstractions
> (pathnames, IP addresses, window ids, whatever) for different objects,
> then I can no longer identify how data can flow throughout the system in
> a system-wide way.

if you are doing a system-wide analysis then you are correct.

the AA approach is to start with the exposed items and limit the damage 
that can be done to you.

sysadmins already think in terms of paths and what can access that path 
(directory permissions), AA extends this in a very natural way and doesn't 
require any special tools or extra steps for normal administration. As a 
result sysadmins are far more likely to use this then they are to touch 
anything that requires that they do a full system analysis before they 
start.

another advantage is that since the policies are independant of each other 
it becomes very easy for software to include sample policies with the 
source.

>>> Um, no.  It might not be able to directly open files via that path, but
>>> showing that it can never read or write your mail is a rather different
>>> matter.
>>>
>> Actually it can be analyzed and shown.  It is ugly to do and we
>> currently don't have a tool capable of doing it, but it is possible.
>
> No, it isn't possible when using ambiguous and unstable identifiers for
> the subjects and objects, nor when mediation is incomplete.

it is possible to say that without assistance from an outside process the 
process cannot access the files containing your mail.

if there is some other method of accessing the content no filesystem-level 
thing can know about it (for example, if another process is a pop server 
that requires no password). but I don't beleive that SELinux policies as 
distributed by any vendor would prevent this (yes, it would be possible 
for a tailored policy to prevent it, but if the policy is so complex that 
only distro staff should touch it that doesn't matter in real life)

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 17:30                                                 ` Chris Mason
@ 2007-06-23  0:11                                                   ` Chris Wright
  2007-06-24  0:10                                                     ` Toshiharu Harada
  2007-06-26 21:01                                                     ` Crispin Cowan
  2007-06-24 20:43                                                   ` Pavel Machek
  1 sibling, 2 replies; 240+ messages in thread
From: Chris Wright @ 2007-06-23  0:11 UTC (permalink / raw)
  To: Chris Mason
  Cc: James Morris, Stephen Smalley, Lars Marowsky-Bree, Pavel Machek,
	Crispin Cowan, Greg KH, Andreas Gruenbacher, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

* Chris Mason (chris.mason@oracle.com) wrote:
> I'm sure people there will have a different versions of events.  The
> one part that was discussed was if pathname based security was
> useful, and a number of the people in the room (outside of 
> novell) said it was.  Now, it could be that nobody wanted to argue
> anymore, since most opinions had come out on one list or another by
> then.  

Indeed.  The trouble is that's too high level compared with the actual
implementation details.  AA is stalled because it has failed to get
VFS support for it's model.  I don't see a nice way out unless it
changes it's notion of policy language (globbing is the tough one)
or gets traction to pass dentry/vfsmount all the way down.  Paths are
completely relevant for security, esp. when considering the parent dir
and the leaf (as in forward lookup case).  Retroactively creating the
full path is at the minimum ugly, and in the worst case can be insecure
(yes AA has taken many measures to mitigate that insecurity).

> But as someone who doesn't use either SElinux or AA, I really hope
> we can get past the part of the debate where:
> 
> while(1)
>     AA) we think we're making users happy with pathname security
>     SELINUX) pathname security sucks

Yes.  Please.  Both parties are miserably failing the sanity test.
Doing the same thing over and over and expecting different results.

AA folks: deal with the VFS issues that your patchset have in a palatable
way (which does not include passing NULL when it's inconvenient to
do otherwise).  You've already missed an opportunity with Christoph's
suggestions for changes in NFS.  I know you've considered many alternative
approaches and consistently hit dead ends.  But please note, if you
have coded yourself into a corner because of your policy language,
that's your issue to solve, not ours.

SELinux folks: do something useful rather than quibbling over the TCSEC
definition of MAC and AA's poor taste in marketing literature.  Here's
some suggestions:

1) Make SELinux usable (it's *still* the number one complaint).  While
this is a bit of a cheap shot, it really is one of the core reasons AA
advocates exist.
2) Work on a variant of Kyle's suggestion to squash the relevancy of AA.
3) Write an effective exploit against AA that demonstrates the fundamental
weakness of the model (better make sure it's not also an issue for
targetted policy).

thanks,
-chris

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-23  0:11                                                   ` Chris Wright
@ 2007-06-24  0:10                                                     ` Toshiharu Harada
  2007-06-24  0:40                                                       ` Toshiharu Harada
  2007-06-26 21:01                                                     ` Crispin Cowan
  1 sibling, 1 reply; 240+ messages in thread
From: Toshiharu Harada @ 2007-06-24  0:10 UTC (permalink / raw)
  To: Chris Wright
  Cc: Chris Mason, James Morris, Stephen Smalley, Lars Marowsky-Bree,
	Pavel Machek, Crispin Cowan, Greg KH, Andreas Gruenbacher,
	jjohansen, linux-kernel, linux-security-module, linux-fsdevel

This thread is amazing.  With so many smart people's precious time,

What are the results?
What are the issues anyway?
Is anyone happy? (I'm not and I assume Chris is not)

Yes, "waste of time" is taking place here, but
it's not for "pathname-based MAC" but for "wrongly posted messages",
I believe.  I'm a relatively new to this ml, let me ask.

Is this ml a place of judge or battle? (not to help or support?)

Nothing is perfect, so we can work to make things to better, right?
I have suggestions:

Let's clarify issues first.
- problems (or limitations) of pathname-based MAC
- advantages of pathname-based MAC
- how can pathname-based MAC supplement label based
(Stephen, James and Kyle, please help)

Let's start the arguments again if we get the issues.
Threads should be definitely separated per issue and
a assigning a chair may help.

Above issues are independent of SELinux. We should not *compare*
SELinux and AA, that can cause a problem. Every software has
shortages that's why we need to work and we can make progress.
For some issues we may need to compare them, in that case
moderators would help.

BTW I have posted a RFC of TOMOYO Linux that is another
pathname-based MAC.
http://lkml.org/lkml/2007/6/13/58
AA and TOMOYO Linux have BoF sessions at OLS2007,
so it would be a great opportunity to *talk* over the issues.

What I want to say is "let's make progress and help each other
to make Linux better".

Thank you,
Toshiharu Harada

Chris Wright wrote:
> * Chris Mason (chris.mason@oracle.com) wrote:
>> I'm sure people there will have a different versions of events.  The
>> one part that was discussed was if pathname based security was
>> useful, and a number of the people in the room (outside of 
>> novell) said it was.  Now, it could be that nobody wanted to argue
>> anymore, since most opinions had come out on one list or another by
>> then.  
> 
> Indeed.  The trouble is that's too high level compared with the actual
> implementation details.  AA is stalled because it has failed to get
> VFS support for it's model.  I don't see a nice way out unless it
> changes it's notion of policy language (globbing is the tough one)
> or gets traction to pass dentry/vfsmount all the way down.  Paths are
> completely relevant for security, esp. when considering the parent dir
> and the leaf (as in forward lookup case).  Retroactively creating the
> full path is at the minimum ugly, and in the worst case can be insecure
> (yes AA has taken many measures to mitigate that insecurity).
> 
>> But as someone who doesn't use either SElinux or AA, I really hope
>> we can get past the part of the debate where:
>>
>> while(1)
>>     AA) we think we're making users happy with pathname security
>>     SELINUX) pathname security sucks
> 
> Yes.  Please.  Both parties are miserably failing the sanity test.
> Doing the same thing over and over and expecting different results.
> 
> AA folks: deal with the VFS issues that your patchset have in a palatable
> way (which does not include passing NULL when it's inconvenient to
> do otherwise).  You've already missed an opportunity with Christoph's
> suggestions for changes in NFS.  I know you've considered many alternative
> approaches and consistently hit dead ends.  But please note, if you
> have coded yourself into a corner because of your policy language,
> that's your issue to solve, not ours.
> 
> SELinux folks: do something useful rather than quibbling over the TCSEC
> definition of MAC and AA's poor taste in marketing literature.  Here's
> some suggestions:
> 
> 1) Make SELinux usable (it's *still* the number one complaint).  While
> this is a bit of a cheap shot, it really is one of the core reasons AA
> advocates exist.
> 2) Work on a variant of Kyle's suggestion to squash the relevancy of AA.
> 3) Write an effective exploit against AA that demonstrates the fundamental
> weakness of the model (better make sure it's not also an issue for
> targetted policy).

-- 
Toshiharu Harada
haradats@nttdata.co.jp


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-24  0:10                                                     ` Toshiharu Harada
@ 2007-06-24  0:40                                                       ` Toshiharu Harada
  0 siblings, 0 replies; 240+ messages in thread
From: Toshiharu Harada @ 2007-06-24  0:40 UTC (permalink / raw)
  Cc: Chris Wright, Chris Mason, James Morris, Stephen Smalley,
	Lars Marowsky-Bree, Pavel Machek, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

> This thread is amazing.  With so many smart people's precious time,
> 
> What are the results?
> What are the issues anyway?
> Is anyone happy? (I'm not and I assume Chris is not)
> 
> Yes, "waste of time" is taking place here, but
> it's not for "pathname-based MAC" but for "wrongly posted messages",
> I believe.  I'm a relatively new to this ml, let me ask.
> 
> Is this ml a place of judge or battle? (not to help or support?)
> 
> Nothing is perfect, so we can work to make things to better, right?
> I have suggestions:
> 
> Let's clarify issues first.
> - problems (or limitations) of pathname-based MAC
> - advantages of pathname-based MAC
> - how can pathname-based MAC supplement label based
> (Stephen, James and Kyle, please help)
> 
> Let's start the arguments again if we get the issues.
> Threads should be definitely separated per issue and
> a assigning a chair may help.

Well, I crated a Wiki page. If it helps, please
feel free to use it.  I mean I would like
people to add your issues here.  It's wiki, so
you are welcome to modify everything.

http://tomoyo.sourceforge.jp/wiki-e/?MAC-ISSUES

If ml is better, I have no objections.
I just wanted to help discussion.

> Above issues are independent of SELinux. We should not *compare*
> SELinux and AA, that can cause a problem. Every software has
> shortages that's why we need to work and we can make progress.
> For some issues we may need to compare them, in that case
> moderators would help.
> 
> BTW I have posted a RFC of TOMOYO Linux that is another
> pathname-based MAC.
> http://lkml.org/lkml/2007/6/13/58
> AA and TOMOYO Linux have BoF sessions at OLS2007,
> so it would be a great opportunity to *talk* over the issues.
> 
> What I want to say is "let's make progress and help each other
> to make Linux better".

Cheers,
Toshiharu Harada


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-21 20:59                                   ` Stephen Smalley
                                                       ` (2 preceding siblings ...)
  2007-06-22  8:06                                     ` John Johansen
@ 2007-06-24 20:35                                     ` David Wagner
  3 siblings, 0 replies; 240+ messages in thread
From: David Wagner @ 2007-06-24 20:35 UTC (permalink / raw)
  To: linux-kernel

Stephen Smalley  wrote:
>On Thu, 2007-06-21 at 21:54 +0200, Lars Marowsky-Bree wrote:
>> And now, yes, I know AA doesn't mediate IPC or networking (yet), but
>> that's a missing feature, not broken by design.
>
>The incomplete mediation flows from the design, since the pathname-based
>mediation doesn't generalize to cover all objects unlike label- or
>attribute-based mediation.

I don't see anything in the AA design that would prevent an extending
it to mediate network and IPC while remaining consistent with its design
so far.  Do you?  It seems to me the AA design is to mediate filesystem
access using pathname-based access control, and that says nothing about
how they mediate network access.

I have built sandboxing tools before, and my experience is that the
filesystem mediation is the hardest, gronkiest part.  In comparison,
mediating networking and IPC is considerably easier.  The policy
language for mediating access to the network can be pretty simple.
The same for IPC.  Obviously you shouldn't expect the policy language
for networking to use filenames, any more than you should expect the
policy languages for filesystems to use TCP/IP port numbers; that wouldn't
make any sense.


>And the "use the natural abstraction for
>each object type" approach likewise doesn't yield any general model or
>anything that you can analyze systematically for data flow.

I don't see this as relevant to whether AA should be merged.
Fight that one in the marketplace for users, not L-K.

>> If I restrict my Mozilla to not access my on-disk mail folder, it can't
>> get there. (Barring bugs in programs which Mozilla is allowed to run
>> unconfined, sure.)
>
>Um, no.  It might not be able to directly open files via that path, but
>showing that it can never read or write your mail is a rather different
>matter.

"Showing that it can never read or write your mail" is not part of AA's
goals.  People whose goals differ from AA's can use a different tool.
No one is forcing you to use AA if it isn't useful to you.

I don't see this criticism as relevant to a merger decision.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 17:30                                                 ` Chris Mason
  2007-06-23  0:11                                                   ` Chris Wright
@ 2007-06-24 20:43                                                   ` Pavel Machek
  1 sibling, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-24 20:43 UTC (permalink / raw)
  To: Chris Mason
  Cc: James Morris, Stephen Smalley, Lars Marowsky-Bree, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

Hi!

> But as someone who doesn't use either SElinux or AA, I really hope
> we can get past the part of the debate where:
> 
> while(1)
>     AA) we think we're making users happy with pathname security
>     SELINUX) pathname security sucks

(Hopefully I'll not be fired for this. :-)

Yes, we _are_ making users happy with AA.

Questions is if we are making them secure. :-).
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 12:20                                           ` Stephen Smalley
@ 2007-06-24 20:45                                             ` David Wagner
  0 siblings, 0 replies; 240+ messages in thread
From: David Wagner @ 2007-06-24 20:45 UTC (permalink / raw)
  To: linux-kernel

Stephen Smalley  wrote:
>That would certainly help, although one might quibble with the use of
>the word "confinement" at all wrt AppArmor (it has a long-established
>technical meaning that implies information flow control, and that goes
>beyond even complete mediation - it requires global and persistent
>protection of the data based on its properties, which requires stable
>and unambiguous identifiers).

1. Yes, that's the usage that has the greatest historical claim, but
"confinement" has also been used in the security community to refer to
limiting the overt side effects a process can have rather than controlling
information flow.  The term "confinement" is arguably ambiguous, but I
think there is a semi-established meaning that doesn't imply information
flow control.

2. This is a can of worms we probably don't want to open.  Keep in
mind that SELinux doesn't meet definition of confinement in Lampson's
original paper, either, because it only restricts overt information flows.
SELinux doesn't prevent covert channels, even though Lampson's original
paper included them as part of the confinement problem.  Yet I don't
think it would be reasonable to criticize someone for describing SELinux
as a tool for "confinement".  I don't know of any practical solution
that solves the confinement problem as Lampson envisioned it.  I'd
recommend making decisions on the basis of whether the mechanisms are
useful, rather than whether they solve Lampson's notion of the
"confinement" problem.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 11:53                                       ` Stephen Smalley
  2007-06-22 12:42                                         ` Lars Marowsky-Bree
  2007-06-22 18:35                                         ` david
@ 2007-06-24 20:48                                         ` David Wagner
  2 siblings, 0 replies; 240+ messages in thread
From: David Wagner @ 2007-06-24 20:48 UTC (permalink / raw)
  To: linux-kernel

Stephen Smalley  wrote:
>On Fri, 2007-06-22 at 01:06 -0700, John Johansen wrote:
>> No the "incomplete" mediation does not flow from the design.  We have
>> deliberately focused on doing the necessary modifications for pathname
>> based mediation.  The IPC and network mediation are a wip.
>
>The fact that you have to go back to the drawing board for them is that
>you didn't get the abstraction right in the first place.

Calling this "going back to the drawing board" board strikes me as an
unfair criticism, when the real situation is that in the future the AA
folks will need to extend their code to mediate network and IPC (not
throw all the current code away and start over from scratch, and not
replace big swaths of the current code).

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 13:48                                           ` James Morris
  2007-06-22 14:02                                             ` Chris Mason
@ 2007-06-24 21:16                                             ` David Wagner
  2007-06-24 21:57                                               ` david
                                                                 ` (2 more replies)
  2007-06-24 21:45                                             ` David Wagner
  2 siblings, 3 replies; 240+ messages in thread
From: David Wagner @ 2007-06-24 21:16 UTC (permalink / raw)
  To: linux-kernel

I've heard four arguments against merging AA.

Argument 1. SELinux does it better than AA.  (Or: SELinux dominates AA.
Or: SELinux can do everything that AA can.)

Argument 2. Object labeling (or: information flow control) is more secure
than pathname-based access control.

Argument 3. AA isn't complete until it mediates network and IPC.

Argument 4. AA doesn't have buy-in from VFS maintainers.

Let me comment on these one-by-one.

1. I think this is a bogus argument for rejecting AA.  As I remember it,
the whole point of LSM was to allow merging multiple solutions and let
them compete for users on their merit, not to force the Linux maintainers
to figure out which is the best solution.  Let a million flowers bloom.

2. This is argument #1 in a different guise and I find it about as weak.
Pathname-based access control has strengths and weaknesses.  I think
users and Linux distributions are in a better position to evaluate those
tradeoffs than L-K.  Competition is good.

3. This one I agree with.  If you want to sandbox network daemons that
you're concerned might get hacked, then you really want your sandbox to
mediate everything.  Right now the security provided by AA (if that's
what you are using it for) will be limited by its incomplete mediation,
since a knowledgeable motivated attacker who hacks your daemon may be
able to use network or IPC to break out of the sandbox, depending upon
the network and host configuration.  Filesystem mediation alone might be
better than nothing, I suppose, if you're worried about script kiddies,
but it's certainly not a basis for strong security claims.  The state of
the art in sandboxing obviously requires complete mediation, and we've
known that for a decade.

That said, I see filesystem mediation as the hard part.  It's the hardest
part to implement and get right.  It's the hardest part to configure
and the hardest part when it comes to designing usable policy languages.
And I suspect it's the hardest part to get merged into the Linux kernel.
And it often makes sense to start with the hard part.  If AA's approach
to mediating the filesystem is acceptable, I think AA is 2/3rds of the way
to a tool that could be very useful for providing strong security claims.

There's a policy decision here: Do maintainers refuse to merge AA until
it provides complete mediation?  That's a policy matter that's up to the
maintainers.  I have no opinion on it.  However if that is the reason
for rejecting AA it seems like it might be appropriate to come to some
decision now about whether AA's approach to filesystem mediation is
acceptable to Linux developers.  I don't think it would be reasonable
to tell AA developers to go spend a few months developing network and
IPC mediation and then after they do that, to reject the whole thing on
the basis that the approach to filesystem mediation is unacceptable.
That won't encourage development of new and innovative approaches to
security, which doesn't seem like a good thing to me.

4. Way over my head.  I'm not qualified to comment on this aspect.
I suspect this is the argument that ought to be getting the most serious
and thorough discussion, not the irrelevant SELinux-vs-AA faceoff.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22  1:06                                       ` James Morris
                                                           ` (2 preceding siblings ...)
  2007-06-22 12:17                                         ` Chris Mason
@ 2007-06-24 21:20                                         ` David Wagner
  3 siblings, 0 replies; 240+ messages in thread
From: David Wagner @ 2007-06-24 21:20 UTC (permalink / raw)
  To: linux-kernel

James Morris  wrote:
>The point is that the pathname model does not generalize, and that 
>AppArmor's inability to provide adequate coverage of the system is a 
>design issue arising from this.

I don't see it.  I don't see why you call this a design issue.  Isn't
this just a case where they haven't gotten around to implementing
network and IPC mediation yet?  How is that a design issue arising
from a pathname-based model?  For instance, one system I built (Janus)
provided complete mediation, including mediation of network and IPC,
yet it too used a pathname model for its policy file when describing
the policy for the filesystem.  That seems to contradict your statement.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 13:48                                           ` James Morris
  2007-06-22 14:02                                             ` Chris Mason
  2007-06-24 21:16                                             ` David Wagner
@ 2007-06-24 21:45                                             ` David Wagner
  2007-06-28 18:31                                               ` Pavel Machek
  2 siblings, 1 reply; 240+ messages in thread
From: David Wagner @ 2007-06-24 21:45 UTC (permalink / raw)
  To: linux-kernel

James Morris  wrote:
>A. Pathname labeling - applying access control to pathnames to objects, 
>rather than labeling the objects themselves.
>
>Think of this as, say, securing your house by putting a gate in the street 
>in front of the house, regardless of how many other possible paths there 
>are to the house via other streets, adjoining properties etc.
>
>Pathname labeling and mediation is simply mediating a well-known path to 
>the object.  In this analogy, object labeling would instead ensure that 
>all of the accessible doors, windows and other entrances of the house were 
>locked, so that someone trying to break in from the rear alley would 
>not get in simply by bypassing the front gate and opening any door.
>
>What you do with AppArmor, instead of addressing the problem, is just 
>redefine the environment along the lines of "set your house into a rock 
>wall so there is only one path to it".

Harrumph.  Those analogies sound good but aren't a very good guide.

Let's take a concrete example.  Consider the following fragment of a
policy for Mozilla:
    allow ~/.mozilla
    deny ~
Ignore the syntax; the goal is to allow Mozilla to access files under
~/.mozilla but nothing else under my home directory.  This is a perfectly
reasonable policy fragment to want to enforce.  And enforcing it in
the obvious way using pathname-based access control is not a ridiculous
thing to do.

Yes, in theory, there could always be crazy symlinks or hardlinks
from somewhere under ~/.mozilla to elsewhere in my home directory that
would cause this policy to behave in ways different from how I desired.
In theory.  But in practice this is "pretty good": good enough to be
useful in the real world.  In the real world I don't have any symlinks
like that under my ~/.mozilla directory, and I'm not really worried
about unconfined processes accidentally creating a symlink under there
against my wishes.  It'd be good enough for me.

Yes, pathname-based models have limitations and weaknesses, but don't
overplay them.  For some purposes they are a very simple way of specifying
a desired policy and they work well enough to be useful -- a darn site
better than what we've got today.  If your goal is "ease of use" and
"better than what many users are using today", it's not an unreasonable
approach.  Time will tell whether it's the best solution, but it's not
obviously wrong.

And I think that's the criteria: If you want to argue that the very
idea of pathname-based access control so bogus that no approach to
pathname-based security should be merged, then you should have to argue
that it is obviously wrong and obviously not useful to users.  I don't
think that burden has been met.

>B. Pathname access control as a general abstraction for OS security.

This strikes me as a strawman.  Pathname-based access control is an
abstraction for mediating the *filesystem*.  Who says it has to be the
way you mediate the network or IPC?

>To quote from:
>
>http://www.novell.com/linux/security/apparmor/
>
>  "AppArmor gives you network application security via mandatory access 
>   control for programs, protecting against the exploitation of software 
>   flaws and compromised systems. AppArmor includes everything you need to 
>   provide effective containment for programs (including those that run as 
>   root) to thwart attempted exploits and even zero-day attacks."
>
>This is not accurate in any sense of the term containment of mandatory 
>access control that I've previously encountered.

You bet.  The claim you quote is totally bogus.

Bad marketers, no biscuit for you.

>The fact that it doesn't work as expected does not arise simply from 
>missing features or being "different".  It arises from the design of the 
>system, which uses a pathname abstraction, where, even if we agree to 
>ignore issue (1) above, still does not work, because only filesystem 
>interactions are mediated.

Disagree.

>The "simple" policy that users can so effortlessly manipulate is simple 
>because it is wrong, and deliberately so.
>
>The design of the AppArmor is based on _appearing simple_, but at the 
>expense of completeness and thus correctness.

Based on my experience with Janus, my expectation is the policy isn't
going to get that much more complicated when they add mediation of
network and IPC access.  I suspect it will stay almost as simple.

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-24 21:16                                             ` David Wagner
@ 2007-06-24 21:57                                               ` david
  2007-06-28 18:13                                               ` Pavel Machek
  2007-06-28 18:19                                               ` Pavel Machek
  2 siblings, 0 replies; 240+ messages in thread
From: david @ 2007-06-24 21:57 UTC (permalink / raw)
  To: David Wagner; +Cc: linux-kernel

On Sun, 24 Jun 2007, David Wagner wrote:

> Argument 3. AA isn't complete until it mediates network and IPC.
>
> Let me comment on these one-by-one.
>
> 3. This one I agree with.  If you want to sandbox network daemons that
> you're concerned might get hacked, then you really want your sandbox to
> mediate everything.  Right now the security provided by AA (if that's
> what you are using it for) will be limited by its incomplete mediation,
> since a knowledgeable motivated attacker who hacks your daemon may be
> able to use network or IPC to break out of the sandbox, depending upon
> the network and host configuration.  Filesystem mediation alone might be
> better than nothing, I suppose, if you're worried about script kiddies,
> but it's certainly not a basis for strong security claims.  The state of
> the art in sandboxing obviously requires complete mediation, and we've
> known that for a decade.

the issue I see is that AA may not have to implement any new in-kernel 
infrastructure to do this.

as recently as yesterday there have been discussions on the netfilter list 
about how to implement filter rules based on the application name (see the 
thread titled 'filter by application name') if this gets implemented 
independantly of AA then AA could provide a policy implementation layer 
over netfilter if desired (or sysadmins could just use their current 
favorite tool to control the network and AA to control the filesystem)

so holding up AA becouse this isn't implemented yet seems to be counter 
productive. people are working on this, and it is going to go in at some 
point independantly of AA, so why tie AA to it?

IPC is a very imprecise term. it includes lots of different ways for 
processes to communicate with each other. some forms of IPC are covered by 
AA today (unix sockets), others aren't. but each of the different methods 
is going to involve some difference in how it's controlled. if you want to 
talk IPC be specific about what IPC methods you are talking bout limiting.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-22 14:02                                             ` Chris Mason
  2007-06-22 14:23                                               ` James Morris
@ 2007-06-25 15:14                                               ` Pavel Machek
  2007-06-25 21:02                                                 ` david
  2007-06-26  8:50                                                 ` Lars Marowsky-Bree
  1 sibling, 2 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-25 15:14 UTC (permalink / raw)
  To: Chris Mason
  Cc: James Morris, Stephen Smalley, Lars Marowsky-Bree, Crispin Cowan,
	Greg KH, Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

Hi!

> We've been over the "AA is different" discussion in threads about a
> billion times, and at the last kernel summit.  I think Lars and others
> have done a pretty good job of describing the problems they are trying
> to solve, can we please move on to discussing technical issues around
> that?

Actually, I surprised Lars a lot by telling him ln /etc/shadow /tmp/
allows any user to make AA ineffective on large part of systems -- in
internal discussion. (It is not actually a _bug_, but it is certainly
unexpected).

(Does it surprise you, too? I'm pretty sure it would surprise many users).

James summarized it nicely:

# The design of the AppArmor is based on _appearing simple_, but at the
# expense of completeness and thus correctness.

If even Lars can be surprised by AAs behaviour, I do not think we can
say "AA is different". I'm afraid that AA is trap for users. It
appears simple, and mostly does what it is told, but does not do _what
user wants_.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-25 15:14                                               ` Pavel Machek
@ 2007-06-25 21:02                                                 ` david
  2007-06-26  8:50                                                 ` Lars Marowsky-Bree
  1 sibling, 0 replies; 240+ messages in thread
From: david @ 2007-06-25 21:02 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Chris Mason, James Morris, Stephen Smalley, Lars Marowsky-Bree,
	Crispin Cowan, Greg KH, Andreas Gruenbacher, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

On Mon, 25 Jun 2007, Pavel Machek wrote:

> Hi!
>
>> We've been over the "AA is different" discussion in threads about a
>> billion times, and at the last kernel summit.  I think Lars and others
>> have done a pretty good job of describing the problems they are trying
>> to solve, can we please move on to discussing technical issues around
>> that?
>
> Actually, I surprised Lars a lot by telling him ln /etc/shadow /tmp/
> allows any user to make AA ineffective on large part of systems -- in
> internal discussion. (It is not actually a _bug_, but it is certainly
> unexpected).
>
> (Does it surprise you, too? I'm pretty sure it would surprise many users).

no, it doesn't surprise me in the least. AA is controlling access to the 
thing called /etc/shadow, if you grant access to it in other ways you 
bypass the restrictions.

if you follow the ln /etc/shadow /tmp/ with chmod 777 /tmp/shadow the 
system is completely insecure.

this is standard stuff that normal sysadmins expect. it's only people who 
have focused on the label approach who would expect it to be any 
different.

> James summarized it nicely:
>
> # The design of the AppArmor is based on _appearing simple_, but at the
> # expense of completeness and thus correctness.
>
> If even Lars can be surprised by AAs behaviour, I do not think we can
> say "AA is different". I'm afraid that AA is trap for users. It
> appears simple, and mostly does what it is told, but does not do _what
> user wants_.

I thought it had been made very clear that hard links like this were a 
potential way around the restrictions, which is why controlled tasks are 
not allowed to do arbatrary hard links.

David Lang

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-25 15:14                                               ` Pavel Machek
  2007-06-25 21:02                                                 ` david
@ 2007-06-26  8:50                                                 ` Lars Marowsky-Bree
  1 sibling, 0 replies; 240+ messages in thread
From: Lars Marowsky-Bree @ 2007-06-26  8:50 UTC (permalink / raw)
  To: Pavel Machek, Chris Mason
  Cc: James Morris, Stephen Smalley, Crispin Cowan, Greg KH,
	Andreas Gruenbacher, jjohansen, linux-kernel,
	linux-security-module, linux-fsdevel

On 2007-06-25T17:14:11, Pavel Machek <pavel@suse.cz> wrote:

> Actually, I surprised Lars a lot by telling him ln /etc/shadow /tmp/
> allows any user to make AA ineffective on large part of systems -- in
> internal discussion. (It is not actually a _bug_, but it is certainly
> unexpected).

Pavel, no, you did not. You _did_ surprise me by misquoting me so badly,
though.

I agreed that actions by not mediated processes can interfere with
mediated processes. That is a given. So you do not give them free access
to a world writable directory.



Regards,
    Lars

-- 
Teamlead Kernel, SuSE Labs, Research and Development
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
"Experience is the name everyone gives to their mistakes." -- Oscar Wilde


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-23  0:11                                                   ` Chris Wright
  2007-06-24  0:10                                                     ` Toshiharu Harada
@ 2007-06-26 21:01                                                     ` Crispin Cowan
  1 sibling, 0 replies; 240+ messages in thread
From: Crispin Cowan @ 2007-06-26 21:01 UTC (permalink / raw)
  To: Chris Wright
  Cc: Chris Mason, James Morris, Stephen Smalley, Lars Marowsky-Bree,
	Pavel Machek, Greg KH, Andreas Gruenbacher, jjohansen,
	linux-kernel, linux-security-module, linux-fsdevel

Chris Wright wrote:
> * Chris Mason (chris.mason@oracle.com) wrote:  
>> I'm sure people there will have a different versions of events.  The
>> one part that was discussed was if pathname based security was
>> useful, and a number of the people in the room (outside of 
>> novell) said it was.  Now, it could be that nobody wanted to argue
>> anymore, since most opinions had come out on one list or another by
>> then.  
>>     
> Indeed.  The trouble is that's too high level compared with the actual
> implementation details.  AA is stalled because it has failed to get
> VFS support for it's model.  I don't see a nice way out unless it
> changes it's notion of policy language (globbing is the tough one)
> or gets traction to pass dentry/vfsmount all the way down.  Paths are
> completely relevant for security, esp. when considering the parent dir
> and the leaf (as in forward lookup case).
To do pathname-based access control in any way, the LSM must be able to
obtain the pathname of an accessed object. The discussion should be
about the best way for an LSM to obtain the pathname of an object being
accessed.

To find the pathname of the object, LSM needs the VFS mount point data.
The VFS owns this information, so the question is the best way to convey
it from VFS to relevant LSM hooks. We are agnostic about how to get that
mount point data, but AFAICT saying that LSM can't see the mount point
data at all is equivalent to rejecting pathname based access control
entirely.

>   Retroactively creating the
> full path is at the minimum ugly, and in the worst case can be insecure
> (yes AA has taken many measures to mitigate that insecurity).
>   
The reverse path construction has been criticized for being both broken
and counter-intuitive. Our secure d_path patch fixes the "broken" part,
it now securely reconstructs the path. The counter-intuitive is because
forward construction of the pathname has unexpected costs, making the
retroactive construction more attractive.

> AA folks: deal with the VFS issues that your patchset have in a palatable
> way (which does not include passing NULL when it's inconvenient to
> do otherwise).
John Johansen posted a patch (written by Andreas Gruenbacher) that
introduced a nameidata2 data structure to try to solve the conditional
null passing problem, but it received no comment. A proper fix to this
problem is clearly desirable, but it also is clearly a defect in NFS and
fixing it is a lot of work; why does AA have to stay outside the kernel
until NFS is fixed, when it can easily adapt to the problem until it is
fixed properly?

>   You've already missed an opportunity with Christoph's
> suggestions for changes in NFS.  I know you've considered many alternative
> approaches and consistently hit dead ends.  But please note, if you
> have coded yourself into a corner because of your policy language,
> that's your issue to solve, not ours.  
I think it is a little more fundamental than that. If you are going to
do pathname based access control at all, you need access to sufficient
information to compute the path name. Can we have a discussion about the
best way to do that?

Crispin

-- 
Crispin Cowan, Ph.D.               http://crispincowan.com/~crispin/
Director of Software Engineering   http://novell.com
	AppArmor Chat: irc.oftc.net/#apparmor


^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-24 21:16                                             ` David Wagner
  2007-06-24 21:57                                               ` david
@ 2007-06-28 18:13                                               ` Pavel Machek
  2007-06-28 18:19                                               ` Pavel Machek
  2 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-28 18:13 UTC (permalink / raw)
  To: David Wagner; +Cc: linux-kernel

Hi!

> I've heard four arguments against merging AA.
> 
> Argument 1. SELinux does it better than AA.  (Or: SELinux dominates AA.
> Or: SELinux can do everything that AA can.)
> 
> Argument 2. Object labeling (or: information flow control) is more secure
> than pathname-based access control.
> 
> Argument 3. AA isn't complete until it mediates network and IPC.
> 
> Argument 4. AA doesn't have buy-in from VFS maintainers.

...

> 1. I think this is a bogus argument for rejecting AA.  As I remember it,
...
> 3. This one I agree with.  If you want to sandbox network daemons that

> 4. Way over my head.  I'm not qualified to comment on this aspect.
> I suspect this is the argument that ought to be getting the most serious
> and thorough discussion, not the irrelevant SELinux-vs-AA faceoff.

I believe situation is 'vfs maintainers seriously dislike AA', but if
they were given good enough reasons -- like 'selinux is broken crap
that does not really work', we probably could twist their arms or
something.

So question is not 'is AA better then SELinux' but 'is AA so much
better than SELinux that we want to overrule vfs maintainers'.

							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-24 21:16                                             ` David Wagner
  2007-06-24 21:57                                               ` david
  2007-06-28 18:13                                               ` Pavel Machek
@ 2007-06-28 18:19                                               ` Pavel Machek
  2 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-28 18:19 UTC (permalink / raw)
  To: David Wagner; +Cc: linux-kernel

Hi!

One more...

> 2. This is argument #1 in a different guise and I find it about as weak.
> Pathname-based access control has strengths and weaknesses.  I think
> users and Linux distributions are in a better position to evaluate those
> tradeoffs than L-K.  Competition is good.

It took you quite a lot of time to realize AA does not do IPC (and all
the implications of that). I do not think Linux _users_ can do
informed decision here. Novell marketing did too good job here.

Heck, even I am not sure if I understand the implications of not doing
IPC confinement. Is shared memory commonly used in a way that allows
exploiting? I know it is a problem, and you probably could kill init
from hacked apache..... but what would you do to break out of jail?

							Pavel
(please cc me)
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-06-24 21:45                                             ` David Wagner
@ 2007-06-28 18:31                                               ` Pavel Machek
  0 siblings, 0 replies; 240+ messages in thread
From: Pavel Machek @ 2007-06-28 18:31 UTC (permalink / raw)
  To: David Wagner; +Cc: linux-kernel

Hi!

> >What you do with AppArmor, instead of addressing the problem, is just 
> >redefine the environment along the lines of "set your house into a rock 
> >wall so there is only one path to it".
> 
> Harrumph.  Those analogies sound good but aren't a very good guide.
> 
> Let's take a concrete example.  Consider the following fragment of a
> policy for Mozilla:
>     allow ~/.mozilla
>     deny ~
> Ignore the syntax; the goal is to allow Mozilla to access files under
> ~/.mozilla but nothing else under my home directory.  This is a perfectly
> reasonable policy fragment to want to enforce.  And enforcing it in
> the obvious way using pathname-based access control is not a ridiculous
> thing to do.

Unfortunately, mozilla needs temporary files IIRC. And when you add
allow /tmp

to your config files, you get system where your fellow users can 
ln HOME/.ssh/identity /tmp/to-steal (or
ln HOME/.profile /tmp/put-evil-code-here)
and AA protection is not effective any more.

Would _you_ do this mistake?

Would our users do this mistake?

Is it right to provide them with auto-learning tools to make this
mistake really easy?

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 240+ messages in thread

* [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
  2007-10-26  6:40 jjohansen
@ 2007-10-26  6:41 ` jjohansen
  0 siblings, 0 replies; 240+ messages in thread
From: jjohansen @ 2007-10-26  6:41 UTC (permalink / raw)
  To: akpm
  Cc: linux-kernel, linux-security-module, John Johansen, Andreas Gruenbacher

[-- Attachment #1: apparmor-module_interface.diff --]
[-- Type: text/plain, Size: 30298 bytes --]

Pathname matching, transition table loading, profile loading and
manipulation.

Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

---
 security/apparmor/match.c            |  273 +++++++++++
 security/apparmor/match.h            |   85 +++
 security/apparmor/module_interface.c |  805 +++++++++++++++++++++++++++++++++++
 3 files changed, 1163 insertions(+)

--- /dev/null
+++ b/security/apparmor/match.c
@@ -0,0 +1,273 @@
+/*
+ *	Copyright (C) 2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	Regular expression transition table matching
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include "apparmor.h"
+#include "match.h"
+
+static struct table_header *unpack_table(void *blob, size_t bsize)
+{
+	struct table_header *table = NULL;
+	struct table_header th;
+	size_t tsize;
+
+	if (bsize < sizeof(struct table_header))
+		goto out;
+
+	th.td_id = be16_to_cpu(*(u16 *) (blob));
+	th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
+	th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
+	blob += sizeof(struct table_header);
+
+	if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
+		th.td_flags == YYTD_DATA8))
+		goto out;
+
+	tsize = table_size(th.td_lolen, th.td_flags);
+	if (bsize < tsize)
+		goto out;
+
+	table = kmalloc(tsize, GFP_KERNEL);
+	if (table) {
+		*table = th;
+		if (th.td_flags == YYTD_DATA8)
+			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
+				     u8, byte_to_byte);
+		else if (th.td_flags == YYTD_DATA16)
+			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
+				     u16, be16_to_cpu);
+		else
+			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
+				     u32, be32_to_cpu);
+	}
+
+out:
+	return table;
+}
+
+int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
+{
+	int hsize, i;
+	int error = -ENOMEM;
+
+	/* get dfa table set header */
+	if (size < sizeof(struct table_set_header))
+		goto fail;
+
+	if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
+		goto fail;
+
+	hsize = ntohl(*(u32 *)(blob + 4));
+	if (size < hsize)
+		goto fail;
+
+	blob += hsize;
+	size -= hsize;
+
+	error = -EPROTO;
+	while (size > 0) {
+		struct table_header *table;
+		table = unpack_table(blob, size);
+		if (!table)
+			goto fail;
+
+		switch(table->td_id) {
+		case YYTD_ID_ACCEPT:
+		case YYTD_ID_BASE:
+			dfa->tables[table->td_id - 1] = table;
+			if (table->td_flags != YYTD_DATA32)
+				goto fail;
+			break;
+		case YYTD_ID_DEF:
+		case YYTD_ID_NXT:
+		case YYTD_ID_CHK:
+			dfa->tables[table->td_id - 1] = table;
+			if (table->td_flags != YYTD_DATA16)
+				goto fail;
+			break;
+		case YYTD_ID_EC:
+			dfa->tables[table->td_id - 1] = table;
+			if (table->td_flags != YYTD_DATA8)
+				goto fail;
+			break;
+		default:
+			kfree(table);
+			goto fail;
+		}
+
+		blob += table_size(table->td_lolen, table->td_flags);
+		size -= table_size(table->td_lolen, table->td_flags);
+	}
+
+	return 0;
+
+fail:
+	for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
+		if (dfa->tables[i]) {
+			kfree(dfa->tables[i]);
+			dfa->tables[i] = NULL;
+		}
+	}
+	return error;
+}
+
+/**
+ * verify_dfa - verify that all the transitions and states in the dfa tables
+ *              are in bounds.
+ * @dfa: dfa to test
+ *
+ * assumes dfa has gone through the verification done by unpacking
+ */
+int verify_dfa(struct aa_dfa *dfa)
+{
+	size_t i, state_count, trans_count;
+	int error = -EPROTO;
+
+	/* check that required tables exist */
+	if (!(dfa->tables[YYTD_ID_ACCEPT -1 ] &&
+	      dfa->tables[YYTD_ID_DEF - 1] &&
+	      dfa->tables[YYTD_ID_BASE - 1] &&
+	      dfa->tables[YYTD_ID_NXT - 1] &&
+	      dfa->tables[YYTD_ID_CHK - 1]))
+		goto out;
+
+	/* accept.size == default.size == base.size */
+	state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
+	if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
+	      state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen))
+		goto out;
+
+	/* next.size == chk.size */
+	trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
+	if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
+		goto out;
+
+	/* if equivalence classes then its table size must be 256 */
+	if (dfa->tables[YYTD_ID_EC - 1] &&
+	    dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
+		goto out;
+
+	for (i = 0; i < state_count; i++) {
+		if (DEFAULT_TABLE(dfa)[i] >= state_count)
+			goto out;
+		if (BASE_TABLE(dfa)[i] >= trans_count + 256)
+			goto out;
+	}
+
+	for (i = 0; i < trans_count ; i++) {
+		if (NEXT_TABLE(dfa)[i] >= state_count)
+			goto out;
+		if (CHECK_TABLE(dfa)[i] >= state_count)
+			goto out;
+	}
+
+	/* verify accept permissions */
+	for (i = 0; i < state_count; i++) {
+		int mode = ACCEPT_TABLE(dfa)[i];
+
+		if (mode & ~AA_VALID_PERM_MASK) {
+			goto out;
+		}
+	}
+
+	error = 0;
+out:
+	return error;
+}
+
+struct aa_dfa *aa_match_alloc(void)
+{
+	return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
+}
+
+void aa_match_free(struct aa_dfa *dfa)
+{
+	if (dfa) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
+			kfree(dfa->tables[i]);
+	}
+	kfree(dfa);
+}
+
+/**
+ * aa_dfa_next_state - traverse @dfa to find state @str stops at
+ * @dfa: the dfa to match @str against
+ * @start: the state of the dfa to start matching in
+ * @str: the string to match against the dfa
+ *
+ * aa_dfa_next_state will match @str against the dfa and return the state it
+ * finished matching in. The final state can be used to look up the accepting
+ * label, or as the start state of a continuing match.
+ */
+unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
+			       const char *str)
+{
+	u16 *def = DEFAULT_TABLE(dfa);
+	u32 *base = BASE_TABLE(dfa);
+	u16 *next = NEXT_TABLE(dfa);
+	u16 *check = CHECK_TABLE(dfa);
+	unsigned int state = start, pos;
+
+	if (state == 0)
+		return 0;
+
+	/* current state is <state>, matching character *str */
+	if (dfa->tables[YYTD_ID_EC - 1]) {
+		u8 *equiv = EQUIV_TABLE(dfa);
+		while (*str) {
+			pos = base[state] + equiv[(u8)*str++];
+			if (check[pos] == state)
+				state = next[pos];
+			else
+				state = def[state];
+		}
+	} else {
+		while (*str) {
+			pos = base[state] + (u8)*str++;
+			if (check[pos] == state)
+				state = next[pos];
+			else
+				state = def[state];
+		}
+	}
+	return state;
+}
+
+/**
+ * aa_dfa_null_transition - step to next state after null character
+ * @dfa: the dfa to match against
+ * @start: the state of the dfa to start matching in
+ *
+ * aa_dfa_null_transition transitions to the next state after a null
+ * character which is not used in standard matching and is only
+ * used to seperate pairs.
+ */
+unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
+{
+	return aa_dfa_next_state(dfa, start, "//");
+}
+
+/**
+ * aa_dfa_match - find accept perm for @str in @state
+ * @dfa: the dfa to match @str against
+ * @str: the path to match against the dfa
+ *
+ * aa_dfa_match will match @str and return the accept perms for the
+ * final state.
+ */
+unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str)
+{
+	return ACCEPT_TABLE(dfa)[aa_dfa_next_state(dfa, DFA_START, str)];
+}
--- /dev/null
+++ b/security/apparmor/match.h
@@ -0,0 +1,85 @@
+/*
+ *	Copyright (C) 2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor submodule (match) prototypes
+ */
+
+#ifndef __MATCH_H
+#define __MATCH_H
+
+#define DFA_START			1
+
+/**
+ * The format used for transition tables is based on the GNU flex table
+ * file format (--tables-file option; see Table File Format in the flex
+ * info pages and the flex sources for documentation). The magic number
+ * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
+ * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
+ * slightly differently (see the apparmor-parser package).
+ */
+
+#define YYTH_MAGIC	0x1B5E783D
+
+struct table_set_header {
+	u32		th_magic;	/* YYTH_MAGIC */
+	u32		th_hsize;
+	u32		th_ssize;
+	u16		th_flags;
+	char		th_version[];
+};
+
+#define	YYTD_ID_ACCEPT	1
+#define YYTD_ID_BASE	2
+#define YYTD_ID_CHK	3
+#define YYTD_ID_DEF	4
+#define YYTD_ID_EC	5
+#define YYTD_ID_META	6
+#define YYTD_ID_NXT	8
+
+
+#define YYTD_DATA8	1
+#define YYTD_DATA16	2
+#define YYTD_DATA32	4
+
+struct table_header {
+	u16		td_id;
+	u16		td_flags;
+	u32		td_hilen;
+	u32		td_lolen;
+	char		td_data[];
+};
+
+#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data))
+#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data))
+#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data))
+#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
+#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
+#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
+
+struct aa_dfa {
+	struct table_header *tables[YYTD_ID_NXT];
+};
+
+#define byte_to_byte(X) (X)
+
+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
+	do { \
+		typeof(LEN) __i; \
+		TYPE *__t = (TYPE *) TABLE; \
+		TYPE *__b = (TYPE *) BLOB; \
+		for (__i = 0; __i < LEN; __i++) { \
+			__t[__i] = NTOHX(__b[__i]); \
+		} \
+	} while (0)
+
+static inline size_t table_size(size_t len, size_t el_size)
+{
+	return ALIGN(sizeof(struct table_header) + len * el_size, 8);
+}
+
+#endif /* __MATCH_H */
--- /dev/null
+++ b/security/apparmor/module_interface.c
@@ -0,0 +1,805 @@
+/*
+ *	Copyright (C) 1998-2007 Novell/SUSE
+ *
+ *	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, version 2 of the
+ *	License.
+ *
+ *	AppArmor userspace policy interface
+ */
+
+#include <asm/unaligned.h>
+
+#include "apparmor.h"
+#include "inline.h"
+
+/*
+ * This mutex is used to synchronize profile adds, replacements, and
+ * removals: we only allow one of these operations at a time.
+ * We do not use the profile list lock here in order to avoid blocking
+ * exec during those operations.  (Exec involves a profile list lookup
+ * for named-profile transitions.)
+ */
+DEFINE_MUTEX(aa_interface_lock);
+
+/*
+ * The AppArmor interface treats data as a type byte followed by the
+ * actual data.  The interface has the notion of a a named entry
+ * which has a name (AA_NAME typecode followed by name string) followed by
+ * the entries typecode and data.  Named types allow for optional
+ * elements and extensions to be added and tested for without breaking
+ * backwards compatability.
+ */
+
+enum aa_code {
+	AA_U8,
+	AA_U16,
+	AA_U32,
+	AA_U64,
+	AA_NAME,	/* same as string except it is items name */
+	AA_STRING,
+	AA_BLOB,
+	AA_STRUCT,
+	AA_STRUCTEND,
+	AA_LIST,
+	AA_LISTEND,
+	AA_ARRAY,
+	AA_ARRAYEND,
+};
+
+/*
+ * aa_ext is the read of the buffer containing the serialized profile.  The
+ * data is copied into a kernel buffer in apparmorfs and then handed off to
+ * the unpack routines.
+ */
+struct aa_ext {
+	void *start;
+	void *end;
+	void *pos;	/* pointer to current position in the buffer */
+	u32 version;
+	char *ns_name;
+};
+
+static inline int aa_inbounds(struct aa_ext *e, size_t size)
+{
+	return (size <= e->end - e->pos);
+}
+
+/**
+ * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
+ * @e: serialized data read head
+ * @chunk: start address for chunk of data
+ *
+ * return the size of chunk found with the read head at the end of
+ * the chunk.
+ */
+static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
+{
+	void *pos = e->pos;
+	size_t size = 0;
+
+	if (!aa_inbounds(e, sizeof(u16)))
+		goto fail;
+	size = le16_to_cpu(get_unaligned((u16 *)e->pos));
+	e->pos += sizeof(u16);
+	if (!aa_inbounds(e, size))
+		goto fail;
+	*chunk = e->pos;
+	e->pos += size;
+	return size;
+
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
+{
+	if (!aa_inbounds(e, 1))
+		return 0;
+	if (*(u8 *) e->pos != code)
+		return 0;
+	e->pos++;
+	return 1;
+}
+
+/**
+ * aa_is_nameX - check is the next element is of type X with a name of @name
+ * @e: serialized data extent information
+ * @code: type code
+ * @name: name to match to the serialized element.
+ *
+ * check that the next serialized data element is of type X and has a tag
+ * name @name.  If @name is specified then there must be a matching
+ * name element in the stream.  If @name is NULL any name element will be
+ * skipped and only the typecode will be tested.
+ * returns 1 on success (both type code and name tests match) and the read
+ * head is advanced past the headers
+ * returns %0 if either match failes, the read head does not move
+ */
+static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
+{
+	void *pos = e->pos;
+	/*
+	 * Check for presence of a tagname, and if present name size
+	 * AA_NAME tag value is a u16.
+	 */
+	if (aa_is_X(e, AA_NAME)) {
+		char *tag;
+		size_t size = aa_is_u16_chunk(e, &tag);
+		/* if a name is specified it must match. otherwise skip tag */
+		if (name && (!size || strcmp(name, tag)))
+			goto fail;
+	} else if (name) {
+		/* if a name is specified and there is no name tag fail */
+		goto fail;
+	}
+
+	/* now check if type code matches */
+	if (aa_is_X(e, code))
+		return 1;
+
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
+{
+	void *pos = e->pos;
+	if (aa_is_nameX(e, AA_U16, name)) {
+		if (!aa_inbounds(e, sizeof(u16)))
+			goto fail;
+		if (data)
+			*data = le16_to_cpu(get_unaligned((u16 *)e->pos));
+		e->pos += sizeof(u16);
+		return 1;
+	}
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
+{
+	void *pos = e->pos;
+	if (aa_is_nameX(e, AA_U32, name)) {
+		if (!aa_inbounds(e, sizeof(u32)))
+			goto fail;
+		if (data)
+			*data = le32_to_cpu(get_unaligned((u32 *)e->pos));
+		e->pos += sizeof(u32);
+		return 1;
+	}
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static size_t aa_is_array(struct aa_ext *e, const char *name)
+{
+	void *pos = e->pos;
+	if (aa_is_nameX(e, AA_ARRAY, name)) {
+		int size;
+		if (!aa_inbounds(e, sizeof(u16)))
+			goto fail;
+		size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
+		e->pos += sizeof(u16);
+		return size;
+	}
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
+{
+	void *pos = e->pos;
+	if (aa_is_nameX(e, AA_BLOB, name)) {
+		u32 size;
+		if (!aa_inbounds(e, sizeof(u32)))
+			goto fail;
+		size = le32_to_cpu(get_unaligned((u32 *)e->pos));
+		e->pos += sizeof(u32);
+		if (aa_inbounds(e, (size_t) size)) {
+			* blob = e->pos;
+			e->pos += size;
+			return size;
+		}
+	}
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
+{
+	char *src_str;
+	size_t size = 0;
+	void *pos = e->pos;
+	*string = NULL;
+	if (aa_is_nameX(e, AA_STRING, name) &&
+	    (size = aa_is_u16_chunk(e, &src_str))) {
+		char *str;
+		if (!(str = kmalloc(size, GFP_KERNEL)))
+			goto fail;
+		memcpy(str, src_str, size);
+		*string = str;
+	}
+
+	return size;
+
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+/**
+ * aa_unpack_dfa - unpack a file rule dfa
+ * @e: serialized data extent information
+ *
+ * returns dfa or ERR_PTR
+ */
+struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
+{
+	char *blob = NULL;
+	size_t size, error = 0;
+	struct aa_dfa *dfa = NULL;
+
+	size = aa_is_blob(e, &blob, "aadfa");
+	if (size) {
+		dfa = aa_match_alloc();
+		if (dfa) {
+			/*
+			 * The dfa is aligned with in the blob to 8 bytes
+			 * from the beginning of the stream.
+			 */
+			size_t sz = blob - (char *) e->start;
+			size_t pad = ALIGN(sz, 8) - sz;
+			error = unpack_dfa(dfa, blob + pad, size - pad);
+			if (!error)
+				error = verify_dfa(dfa);
+		} else {
+			error = -ENOMEM;
+		}
+
+		if (error) {
+			aa_match_free(dfa);
+			dfa = ERR_PTR(error);
+		}
+	}
+
+	return dfa;
+}
+
+/**
+ * aa_unpack_profile - unpack a serialized profile
+ * @e: serialized data extent information
+ * @operation: operation profile is being unpacked for
+ */
+static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
+					    const char *operation)
+{
+	struct aa_profile *profile = NULL;
+	struct aa_audit sa;
+
+	int error = -EPROTO;
+
+	profile = alloc_aa_profile();
+	if (!profile)
+		return ERR_PTR(-ENOMEM);
+
+	/* check that we have the right struct being passed */
+	if (!aa_is_nameX(e, AA_STRUCT, "profile"))
+		goto fail;
+	if (!aa_is_dynstring(e, &profile->name, NULL))
+		goto fail;
+
+	/* per profile debug flags (complain, audit) */
+	if (!aa_is_nameX(e, AA_STRUCT, "flags"))
+		goto fail;
+	if (!aa_is_u32(e, NULL, NULL))
+		goto fail;
+	if (!aa_is_u32(e, &(profile->flags.complain), NULL))
+		goto fail;
+	if (!aa_is_u32(e, &(profile->flags.audit), NULL))
+		goto fail;
+	if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+		goto fail;
+
+	if (!aa_is_u32(e, &(profile->capabilities), NULL))
+		goto fail;
+
+	/* get file rules */
+	profile->file_rules = aa_unpack_dfa(e);
+	if (IS_ERR(profile->file_rules)) {
+		error = PTR_ERR(profile->file_rules);
+		profile->file_rules = NULL;
+		goto fail;
+	}
+
+	if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+		goto fail;
+
+	return profile;
+
+fail:
+	memset(&sa, 0, sizeof(sa));
+	sa.operation = operation;
+	sa.gfp_mask = GFP_KERNEL;
+	sa.name = profile && profile->name ? profile->name : "unknown";
+	if (!sa.info)
+		sa.info = "failed to unpack profile";
+	aa_audit_status(NULL, &sa);
+
+	if (profile)
+		free_aa_profile(profile);
+
+	return ERR_PTR(error);
+}
+
+/**
+ * aa_verify_head - unpack serialized stream header
+ * @e: serialized data read head
+ * @operation: operation header is being verified for
+ *
+ * returns error or 0 if header is good
+ */
+static int aa_verify_header(struct aa_ext *e, const char *operation)
+{
+	/* get the interface version */
+	if (!aa_is_u32(e, &e->version, "version")) {
+		struct aa_audit sa;
+		memset(&sa, 0, sizeof(sa));
+		sa.operation = operation;
+		sa.gfp_mask = GFP_KERNEL;
+		sa.info = "invalid profile format";
+		aa_audit_status(NULL, &sa);
+		return -EPROTONOSUPPORT;
+	}
+
+	/* check that the interface version is currently supported */
+	if (e->version != 3) {
+		struct aa_audit sa;
+		memset(&sa, 0, sizeof(sa));
+		sa.operation = operation;
+		sa.gfp_mask = GFP_KERNEL;
+		sa.info = "unsupported interface version";
+		aa_audit_status(NULL, &sa);
+		return -EPROTONOSUPPORT;
+	}
+
+	/* read the namespace if present */
+	if (!aa_is_dynstring(e, &e->ns_name, "namespace")) {
+		e->ns_name = NULL;
+	}
+
+	return 0;
+}
+
+/**
+ * aa_add_profile - Unpack and add a new profile to the profile list
+ * @data: serialized data stream
+ * @size: size of the serialized data stream
+ */
+ssize_t aa_add_profile(void *data, size_t size)
+{
+	struct aa_profile *profile = NULL;
+	struct aa_namespace *ns = NULL;
+	struct aa_ext e = {
+		.start = data,
+		.end = data + size,
+		.pos = data,
+		.ns_name = NULL
+	};
+	ssize_t error = aa_verify_header(&e, "profile_load");
+	if (error)
+		return error;
+
+	profile = aa_unpack_profile(&e, "profile_load");
+	if (IS_ERR(profile))
+		return PTR_ERR(profile);
+
+	mutex_lock(&aa_interface_lock);
+	write_lock(&profile_ns_list_lock);
+	if (e.ns_name)
+		ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
+	else
+		ns = default_namespace;
+	if (!ns) {
+		struct aa_namespace *new_ns;
+		write_unlock(&profile_ns_list_lock);
+		new_ns = alloc_aa_namespace(e.ns_name);
+		if (!new_ns) {
+			mutex_unlock(&aa_interface_lock);
+			return -ENOMEM;
+		}
+		write_lock(&profile_ns_list_lock);
+		ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
+		if (!ns) {
+			list_add(&new_ns->list, &profile_ns_list);
+			ns = new_ns;
+		} else
+			free_aa_namespace(new_ns);
+	}
+
+	write_lock(&ns->lock);
+	if (__aa_find_profile(profile->name, &ns->profiles)) {
+		/* A profile with this name exists already. */
+		write_unlock(&ns->lock);
+		write_unlock(&profile_ns_list_lock);
+		mutex_unlock(&aa_interface_lock);
+		aa_put_profile(profile);
+		return -EEXIST;
+	}
+	profile->ns = aa_get_namespace(ns);
+	ns->profile_count++;
+	list_add(&profile->list, &ns->profiles);
+	write_unlock(&ns->lock);
+	write_unlock(&profile_ns_list_lock);
+	mutex_unlock(&aa_interface_lock);
+
+	return size;
+}
+
+/**
+ * task_replace - replace a task's profile
+ * @task: task to replace profile on
+ * @new_cxt: new aa_task_context to do replacement with
+ * @new_profile: new profile
+ */
+static inline void task_replace(struct task_struct *task,
+				struct aa_task_context *new_cxt,
+				struct aa_profile *new_profile)
+{
+	struct aa_task_context *cxt = aa_task_context(task);
+
+	AA_DEBUG("%s: replacing profile for task %d "
+		 "profile=%s (%p)\n",
+		 __FUNCTION__,
+		 cxt->task->pid,
+		 cxt->profile->name, cxt->profile);
+
+	aa_change_task_context(task, new_cxt, new_profile, cxt->cookie,
+			       cxt->previous_profile);
+}
+
+/**
+ * aa_replace_profile - replace a profile on the profile list
+ * @udata: serialized data stream
+ * @size: size of the serialized data stream
+ *
+ * unpack and replace a profile on the profile list and uses of that profile
+ * by any aa_task_context.  If the profile does not exist on the profile list
+ * it is added.  Return %0 or error.
+ */
+ssize_t aa_replace_profile(void *udata, size_t size)
+{
+	struct aa_profile *old_profile, *new_profile;
+	struct aa_namespace *ns;
+	struct aa_task_context *new_cxt;
+	struct aa_ext e = {
+		.start = udata,
+		.end = udata + size,
+		.pos = udata,
+		.ns_name = NULL
+	};
+
+	ssize_t error = aa_verify_header(&e, "profile_replace");
+	if (error)
+		return error;
+
+	new_profile = aa_unpack_profile(&e, "profile_replace");
+	if (IS_ERR(new_profile))
+		return PTR_ERR(new_profile);
+
+	mutex_lock(&aa_interface_lock);
+	write_lock(&profile_ns_list_lock);
+	if (e.ns_name)
+		ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
+	else
+		ns = default_namespace;
+	if (!ns) {
+		struct aa_namespace *new_ns;
+		write_unlock(&profile_ns_list_lock);
+		new_ns = alloc_aa_namespace(e.ns_name);
+		if (!new_ns) {
+			mutex_unlock(&aa_interface_lock);
+			return -ENOMEM;
+		}
+		write_lock(&profile_ns_list_lock);
+		ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
+		if (!ns) {
+			list_add(&new_ns->list, &profile_ns_list);
+			ns = new_ns;
+		} else
+			free_aa_namespace(new_ns);
+	}
+
+	write_lock(&ns->lock);
+	old_profile = __aa_find_profile(new_profile->name, &ns->profiles);
+	if (old_profile) {
+		lock_profile(old_profile);
+		old_profile->isstale = 1;
+		list_del_init(&old_profile->list);
+		unlock_profile(old_profile);
+		ns->profile_count--;
+	}
+	new_profile->ns = aa_get_namespace(ns);
+	ns->profile_count++;
+	list_add(&new_profile->list, &ns->profiles);
+	write_unlock(&ns->lock);
+	write_unlock(&profile_ns_list_lock);
+
+	if (!old_profile)
+		goto out;
+
+	/*
+	 * Replacement needs to allocate a new aa_task_context for each
+	 * task confined by old_profile.  To do this the profile locks
+	 * are only held when the actual switch is done per task.  While
+	 * looping to allocate a new aa_task_context the old_task list
+	 * may get shorter if tasks exit/change their profile but will
+	 * not get longer as new task will not use old_profile detecting
+	 * that is stale.
+	 */
+	do {
+		new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
+
+		lock_both_profiles(old_profile, new_profile);
+		if (!list_empty(&old_profile->task_contexts)) {
+			struct task_struct *task =
+				list_entry(old_profile->task_contexts.next,
+					   struct aa_task_context, list)->task;
+			task_lock(task);
+			task_replace(task, new_cxt, new_profile);
+			task_unlock(task);
+			new_cxt = NULL;
+		}
+		unlock_both_profiles(old_profile, new_profile);
+	} while (!new_cxt);
+	aa_free_task_context(new_cxt);
+	aa_put_profile(old_profile);
+
+out:
+	mutex_unlock(&aa_interface_lock);
+	return size;
+}
+
+/**
+ * aa_remove_profile - remove a profile from the system
+ * @name: name of the profile to remove
+ * @size: size of the name
+ *
+ * remove a profile from the profile list and all aa_task_context references
+ * to said profile.
+ */
+ssize_t aa_remove_profile(char *name, size_t size)
+{
+	struct aa_namespace *ns;
+	struct aa_profile *profile;
+
+	mutex_lock(&aa_interface_lock);
+	write_lock(&profile_ns_list_lock);
+
+	if (name[0] == '/') {
+		ns = default_namespace;
+	} else {
+		char *split = strchr(name, ':');
+		if (!split)
+			goto noent;
+		*split = 0;
+		ns = __aa_find_namespace(name, &profile_ns_list);
+		name = split + 1;
+	}
+
+	if (!ns)
+		goto noent;
+	write_lock(&ns->lock);
+	profile = __aa_find_profile(name, &ns->profiles);
+	if (!profile) {
+		write_unlock(&ns->lock);
+		goto noent;
+	}
+
+	/* Remove the profile from each task context it is on. */
+	lock_profile(profile);
+	profile->isstale = 1;
+	aa_unconfine_tasks(profile);
+	list_del_init(&profile->list);
+	ns->profile_count--;
+	unlock_profile(profile);
+	/* Release the profile itself. */
+	write_unlock(&ns->lock);
+	/* check to see if the namespace has become stale */
+	if (ns != default_namespace && ns->profile_count == 0) {
+		list_del_init(&ns->list);
+		aa_put_namespace(ns);
+	}
+	write_unlock(&profile_ns_list_lock);
+	mutex_unlock(&aa_interface_lock);
+	aa_put_profile(profile);
+
+	return size;
+
+noent:
+	write_unlock(&profile_ns_list_lock);
+	mutex_unlock(&aa_interface_lock);
+	return -ENOENT;
+}
+
+/**
+ * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
+ * @kr: kref callback for freeing of a namespace
+ */
+void free_aa_namespace_kref(struct kref *kref)
+{
+	struct aa_namespace *ns=container_of(kref, struct aa_namespace, count);
+
+	free_aa_namespace(ns);
+}
+
+/**
+ * alloc_aa_namespace - allocate, initialize and return a new namespace
+ * @name: a preallocated name
+ * Returns NULL on failure.
+ */
+struct aa_namespace *alloc_aa_namespace(char *name)
+{
+	struct aa_namespace *ns;
+
+	ns = kzalloc(sizeof(*ns), GFP_KERNEL);
+	AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
+	if (ns) {
+		ns->name = name;
+		INIT_LIST_HEAD(&ns->list);
+		INIT_LIST_HEAD(&ns->profiles);
+		kref_init(&ns->count);
+		rwlock_init(&ns->lock);
+
+		ns->null_complain_profile = alloc_aa_profile();
+		if (!ns->null_complain_profile) {
+			if (!name)
+				kfree(ns->name);
+			kfree(ns);
+			return NULL;
+		}
+		ns->null_complain_profile->name =
+			kstrdup("null-complain-profile", GFP_KERNEL);
+		if (!ns->null_complain_profile->name) {
+			free_aa_profile(ns->null_complain_profile);
+			if (!name)
+				kfree(ns->name);
+			kfree(ns);
+			return NULL;
+		}
+		ns->null_complain_profile->flags.complain = 1;
+		/* null_complain_profile doesn't contribute to ns ref count */
+		ns->null_complain_profile->ns = ns;
+	}
+	return ns;
+}
+
+/**
+ * free_aa_namespace - free a profile namespace
+ * @namespace: the namespace to free
+ *
+ * Free a namespace.  All references to the namespace must have been put.
+ * If the namespace was referenced by a profile confining a task,
+ * free_aa_namespace will be called indirectly (through free_aa_profile)
+ * from an rcu callback routine, so we must not sleep here.
+ */
+void free_aa_namespace(struct aa_namespace *ns)
+{
+	AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
+
+	if (!ns)
+		return;
+
+	/* namespace still contains profiles -- invalid */
+	if (!list_empty(&ns->profiles)) {
+		AA_ERROR("%s: internal error, "
+			 "namespace '%s' still contains profiles\n",
+			 __FUNCTION__,
+			 ns->name);
+		BUG();
+	}
+	if (!list_empty(&ns->list)) {
+		AA_ERROR("%s: internal error, "
+			 "namespace '%s' still on list\n",
+			 __FUNCTION__,
+			 ns->name);
+		BUG();
+	}
+	/* null_complain_profile doesn't contribute to ns ref counting */
+	ns->null_complain_profile->ns = NULL;
+	aa_put_profile(ns->null_complain_profile);
+	kfree(ns->name);
+	kfree(ns);
+}
+
+/**
+ * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
+ * @kr: kref callback for freeing of a profile
+ */
+void free_aa_profile_kref(struct kref *kref)
+{
+	struct aa_profile *p=container_of(kref, struct aa_profile, count);
+
+	free_aa_profile(p);
+}
+
+/**
+ * alloc_aa_profile - allocate, initialize and return a new profile
+ * Returns NULL on failure.
+ */
+struct aa_profile *alloc_aa_profile(void)
+{
+	struct aa_profile *profile;
+
+	profile = kzalloc(sizeof(*profile), GFP_KERNEL);
+	AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
+	if (profile) {
+		INIT_LIST_HEAD(&profile->list);
+		kref_init(&profile->count);
+		INIT_LIST_HEAD(&profile->task_contexts);
+		spin_lock_init(&profile->lock);
+	}
+	return profile;
+}
+
+/**
+ * free_aa_profile - free a profile
+ * @profile: the profile to free
+ *
+ * Free a profile, its hats and null_profile. All references to the profile,
+ * its hats and null_profile must have been put.
+ *
+ * If the profile was referenced from a task context, free_aa_profile() will
+ * be called from an rcu callback routine, so we must not sleep here.
+ */
+void free_aa_profile(struct aa_profile *profile)
+{
+	AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
+
+	if (!profile)
+		return;
+
+	/* profile is still on profile namespace list -- invalid */
+	if (!list_empty(&profile->list)) {
+		AA_ERROR("%s: internal error, "
+			 "profile '%s' still on global list\n",
+			 __FUNCTION__,
+			 profile->name);
+		BUG();
+	}
+	aa_put_namespace(profile->ns);
+
+	aa_match_free(profile->file_rules);
+
+	if (profile->name) {
+		AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
+		kfree(profile->name);
+	}
+
+	kfree(profile);
+}
+
+/**
+ * aa_unconfine_tasks - remove tasks on a profile's task context list
+ * @profile: profile to remove tasks from
+ *
+ * Assumes that @profile lock is held.
+ */
+void aa_unconfine_tasks(struct aa_profile *profile)
+{
+	while (!list_empty(&profile->task_contexts)) {
+		struct task_struct *task =
+			list_entry(profile->task_contexts.next,
+				   struct aa_task_context, list)->task;
+		task_lock(task);
+		aa_change_task_context(task, NULL, NULL, 0, NULL);
+		task_unlock(task);
+	}
+}

-- 


^ permalink raw reply	[flat|nested] 240+ messages in thread

end of thread, other threads:[~2007-10-26  7:12 UTC | newest]

Thread overview: 240+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-05-14 11:06 [AppArmor 00/45] AppArmor security module overview jjohansen
2007-05-14 11:06 ` [AppArmor 01/45] Pass struct vfsmount to the inode_create LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 02/45] Pass struct path down to remove_suid and children jjohansen
2007-05-14 11:06 ` [AppArmor 03/45] Add a vfsmount parameter to notify_change() jjohansen
2007-05-14 11:06 ` [AppArmor 04/45] Pass struct vfsmount to the inode_setattr LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 05/45] Add struct vfsmount parameter to vfs_mkdir() jjohansen
2007-05-14 11:06 ` [AppArmor 06/45] Pass struct vfsmount to the inode_mkdir LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 07/45] Add a struct vfsmount parameter to vfs_mknod() jjohansen
2007-05-14 11:06 ` [AppArmor 08/45] Pass struct vfsmount to the inode_mknod LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 09/45] Add a struct vfsmount parameter to vfs_symlink() jjohansen
2007-05-14 11:06 ` [AppArmor 10/45] Pass struct vfsmount to the inode_symlink LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 11/45] Pass struct vfsmount to the inode_readlink " jjohansen
2007-05-14 11:06 ` [AppArmor 12/45] Add struct vfsmount parameters to vfs_link() jjohansen
2007-05-14 11:06 ` [AppArmor 13/45] Pass the struct vfsmounts to the inode_link LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 14/45] Add a struct vfsmount parameter to vfs_rmdir() jjohansen
2007-05-14 11:06 ` [AppArmor 15/45] Pass struct vfsmount to the inode_rmdir LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 16/45] Call lsm hook before unhashing dentry in vfs_rmdir() jjohansen
2007-05-14 11:06 ` [AppArmor 17/45] Add a struct vfsmount parameter to vfs_unlink() jjohansen
2007-05-14 11:06 ` [AppArmor 18/45] Pass struct vfsmount to the inode_unlink LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 19/45] Add struct vfsmount parameters to vfs_rename() jjohansen
2007-05-14 11:06 ` [AppArmor 20/45] Pass struct vfsmount to the inode_rename LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 21/45] Add a struct vfsmount parameter to vfs_setxattr() jjohansen
2007-05-14 11:06 ` [AppArmor 22/45] Pass struct vfsmount to the inode_setxattr LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 23/45] Add a struct vfsmount parameter to vfs_getxattr() jjohansen
2007-05-14 11:06 ` [AppArmor 24/45] Pass struct vfsmount to the inode_getxattr LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 25/45] Add a struct vfsmount parameter to vfs_listxattr() jjohansen
2007-05-14 11:06 ` [AppArmor 26/45] Pass struct vfsmount to the inode_listxattr LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 27/45] Add a struct vfsmount parameter to vfs_removexattr() jjohansen
2007-05-14 11:06 ` [AppArmor 28/45] Pass struct vfsmount to the inode_removexattr LSM hook jjohansen
2007-05-14 11:06 ` [AppArmor 29/45] Fix __d_path() for lazy unmounts and make it unambiguous jjohansen
2007-05-14 11:06 ` [AppArmor 30/45] Make d_path() consistent across mount operations jjohansen
2007-05-14 11:06 ` [AppArmor 31/45] Add d_namespace_path() to compute namespace relative pathnames jjohansen
2007-05-14 11:06 ` [AppArmor 32/45] Enable LSM hooks to distinguish operations on file descriptors from operations on pathnames jjohansen
2007-05-14 11:06 ` [AppArmor 33/45] Pass struct file down the inode_*xattr security LSM hooks jjohansen
2007-05-14 11:06 ` [AppArmor 34/45] Factor out sysctl pathname code jjohansen
2007-05-14 11:06 ` [AppArmor 35/45] Allow permission functions to tell between parent and leaf checks jjohansen
2007-05-15  9:08   ` Pavel Machek
2007-05-14 11:06 ` [AppArmor 36/45] Export audit subsystem for use by modules jjohansen
2007-05-14 11:06 ` [AppArmor 37/45] AppArmor: Main Part jjohansen
2007-05-15  9:12   ` Pavel Machek
2007-05-14 11:06 ` [AppArmor 38/45] AppArmor: Module and LSM hooks jjohansen
2007-05-15  9:14   ` Pavel Machek
2007-05-23 16:16     ` Andreas Gruenbacher
2007-06-04 10:55       ` Pavel Machek
2007-06-04 11:25         ` Andreas Gruenbacher
2007-06-04 11:35           ` Pavel Machek
2007-06-04 11:42             ` Andreas Gruenbacher
2007-06-04 13:12               ` Pavel Machek
2007-06-04 14:30                 ` Andreas Gruenbacher
2007-06-06 13:09                   ` Stephen Smalley
2007-06-10 23:10                     ` Andreas Gruenbacher
2007-06-11 14:33                       ` Stephen Smalley
2007-06-11 15:55                         ` Andreas Gruenbacher
2007-06-11 19:02                           ` Serge E. Hallyn
2007-06-12 13:00                             ` Stephen Smalley
2007-06-12 15:34                               ` Serge E. Hallyn
2007-06-12  5:17                                 ` Karl MacMillan
2007-06-12 19:00                                   ` Serge E. Hallyn
2007-06-12 13:13                           ` Stephen Smalley
2007-06-12 23:50                         ` Andreas Gruenbacher
2007-06-09 12:58                   ` Pavel Machek
2007-06-09 13:44                     ` Andreas Gruenbacher
2007-06-12 13:06                       ` Pavel Machek
2007-05-14 11:06 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching jjohansen
2007-05-15  9:20   ` Pavel Machek
2007-06-04 21:03     ` Andreas Gruenbacher
2007-06-06 13:26       ` Stephen Smalley
2007-06-06 17:32         ` Greg KH
2007-06-09 23:47           ` Pavel Machek
2007-06-08 22:03         ` Andreas Gruenbacher
2007-06-09  0:17           ` Greg KH
2007-06-09  1:06             ` david
2007-06-09  2:01               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
2007-06-09  3:25                 ` Sean
2007-06-09  4:56                   ` david
2007-06-09  5:10                     ` Sean
2007-06-09  5:38                       ` david
2007-06-09  5:44                         ` Sean
2007-06-09  7:04                           ` david
2007-06-09  7:28                             ` Sean
2007-06-09  8:03                               ` david
2007-06-09  8:37                                 ` Sean
2007-06-14 17:01                                 ` Pavel Machek
2007-06-09 11:26                               ` [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching Tetsuo Handa
2007-06-09 11:35                                 ` Sean
2007-06-09 13:41                                   ` david
2007-06-09 18:37                               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Casey Schaufler
2007-06-15 13:36                                 ` Pavel Machek
2007-06-10  8:34               ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Pavel Machek
2007-06-10  9:04                 ` david
2007-06-10 20:04                   ` Casey Schaufler
2007-06-10 20:51                     ` Crispin Cowan
2007-06-11  6:45                       ` david
2007-06-11  8:29                         ` Sean
2007-06-11  9:33                           ` david
2007-06-11 11:34                             ` Sean
2007-06-11 11:00                         ` Pavel Machek
2007-06-10 21:05                   ` Pavel Machek
2007-06-11  6:27                     ` david
2007-06-14 19:16                       ` Jack Stone
2007-06-15  0:18                         ` david
2007-06-15 17:01                           ` Greg KH
2007-06-12 17:03                     ` Lars Marowsky-Bree
2007-06-09  5:18             ` david
2007-06-09  5:46               ` Sean
2007-06-09  7:13                 ` david
2007-06-09  7:36                   ` Sean
2007-06-09  8:06                     ` david
2007-06-09  8:10                       ` Sean
2007-06-09 15:17                         ` Andreas Gruenbacher
2007-06-09 16:36                           ` Sean
2007-06-09 15:33                   ` Joshua Brindle
2007-06-09 16:18               ` Kyle Moffett
2007-06-09 16:46                 ` david
2007-06-09 17:06                   ` Kyle Moffett
2007-06-09 17:32                     ` david
2007-06-09 19:50                       ` Kyle Moffett
2007-06-09 20:43                         ` david
2007-06-10 20:54               ` Crispin Cowan
2007-06-10 21:17                 ` Joshua Brindle
2007-06-09 15:05             ` Andreas Gruenbacher
2007-06-10 17:09             ` Crispin Cowan
2007-06-15 16:50               ` Greg KH
2007-06-15 18:01                 ` Casey Schaufler
2007-06-15 18:15                   ` Stephen Smalley
2007-06-15 20:43                     ` Casey Schaufler
2007-06-15 21:14                       ` Greg KH
2007-06-15 21:28                         ` Karl MacMillan
2007-06-15 21:44                           ` Greg KH
2007-06-15 22:24                             ` Karl MacMillan
2007-06-18 13:33                               ` Stephen Smalley
2007-06-21 15:54                                 ` Andreas Gruenbacher
2007-06-15 22:37                         ` Casey Schaufler
2007-06-18 12:47                       ` Stephen Smalley
2007-06-15 20:06                 ` Pavel Machek
2007-06-15 21:11                   ` Greg KH
2007-06-15 21:42                     ` James Morris
2007-06-15 23:50                       ` Greg KH
2007-06-16  1:21                         ` James Morris
2007-06-16  2:57                           ` Casey Schaufler
2007-06-16  3:39                             ` James Morris
2007-06-18  1:51                               ` Casey Schaufler
2007-06-18 11:29                                 ` Joshua Brindle
2007-06-16  4:23                           ` Greg KH
2007-06-15 23:30                     ` Crispin Cowan
2007-06-15 23:49                       ` Greg KH
2007-06-16  0:01                         ` david
2007-06-16  0:20                           ` Pavel Machek
2007-06-22  9:59                             ` Andreas Gruenbacher
2007-06-16  0:31                           ` Greg KH
2007-06-16  8:09                             ` david
2007-06-16 16:24                               ` Greg KH
2007-06-16  1:41                           ` James Morris
2007-06-16  0:18                         ` Seth Arnold
2007-06-16  0:29                           ` Greg KH
2007-06-16  1:46                           ` James Morris
2007-06-16  2:19                           ` James Morris
2007-06-18 18:48                         ` Crispin Cowan
2007-06-21 16:01                         ` Andreas Gruenbacher
2007-06-21 17:59                           ` Pavel Machek
2007-06-16  0:02                       ` Pavel Machek
2007-06-21 16:08                         ` Lars Marowsky-Bree
2007-06-21 18:33                           ` Pavel Machek
2007-06-21 19:24                             ` Lars Marowsky-Bree
2007-06-21 19:42                               ` James Morris
2007-06-21 19:54                                 ` Lars Marowsky-Bree
2007-06-21 20:59                                   ` Stephen Smalley
2007-06-21 21:17                                     ` Lars Marowsky-Bree
2007-06-22  0:16                                       ` Joshua Brindle
2007-06-22  0:19                                         ` Lars Marowsky-Bree
2007-06-22  0:28                                         ` david
2007-06-22  3:45                                           ` Joshua Brindle
2007-06-22  5:07                                             ` david
2007-06-22 10:49                                             ` Lars Marowsky-Bree
2007-06-22 11:19                                       ` Stephen Smalley
2007-06-22 11:34                                         ` Neil Brown
2007-06-22 11:48                                           ` Stephen Smalley
2007-06-22 11:37                                         ` Lars Marowsky-Bree
2007-06-22 12:41                                           ` Stephen Smalley
2007-06-22 12:54                                             ` Lars Marowsky-Bree
2007-06-22 13:22                                               ` Stephen Smalley
2007-06-22 14:49                                                 ` Stephen Smalley
2007-06-22 16:06                                             ` Casey Schaufler
2007-06-22  0:34                                     ` Chris Mason
2007-06-22  1:06                                       ` James Morris
2007-06-22  4:17                                         ` Crispin Cowan
2007-06-22 12:20                                           ` Stephen Smalley
2007-06-24 20:45                                             ` David Wagner
2007-06-22  7:40                                         ` John Johansen
2007-06-22 12:17                                         ` Chris Mason
2007-06-22 13:48                                           ` James Morris
2007-06-22 14:02                                             ` Chris Mason
2007-06-22 14:23                                               ` James Morris
2007-06-22 17:30                                                 ` Chris Mason
2007-06-23  0:11                                                   ` Chris Wright
2007-06-24  0:10                                                     ` Toshiharu Harada
2007-06-24  0:40                                                       ` Toshiharu Harada
2007-06-26 21:01                                                     ` Crispin Cowan
2007-06-24 20:43                                                   ` Pavel Machek
2007-06-22 18:12                                                 ` david
2007-06-25 15:14                                               ` Pavel Machek
2007-06-25 21:02                                                 ` david
2007-06-26  8:50                                                 ` Lars Marowsky-Bree
2007-06-24 21:16                                             ` David Wagner
2007-06-24 21:57                                               ` david
2007-06-28 18:13                                               ` Pavel Machek
2007-06-28 18:19                                               ` Pavel Machek
2007-06-24 21:45                                             ` David Wagner
2007-06-28 18:31                                               ` Pavel Machek
2007-06-24 21:20                                         ` David Wagner
2007-06-22  8:06                                     ` John Johansen
2007-06-22 11:53                                       ` Stephen Smalley
2007-06-22 12:42                                         ` Lars Marowsky-Bree
2007-06-22 12:46                                           ` Stephen Smalley
2007-06-22 18:35                                         ` david
2007-06-24 20:48                                         ` David Wagner
2007-06-24 20:35                                     ` David Wagner
2007-06-21 20:07                               ` Pavel Machek
2007-06-21 20:21                                 ` Lars Marowsky-Bree
2007-06-21 23:25                                   ` John Johansen
2007-06-21 19:30                             ` david
2007-06-21 19:35                               ` Lars Marowsky-Bree
2007-06-21 19:52                               ` Pavel Machek
2007-06-16  0:48                       ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
2007-06-19 15:25                         ` Pavel Machek
2007-06-15 23:33                   ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Seth Arnold
2007-06-15 23:39                     ` Pavel Machek
2007-06-16  0:07                       ` Seth Arnold
2007-06-16 15:44                 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation,pathname matching Tetsuo Handa
2007-06-16 16:26                   ` Greg KH
2007-06-16 16:45                     ` [AppArmor 39/45] AppArmor: Profile loading andmanipulation,pathname matching Tetsuo Handa
2007-06-11 15:16           ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching Stephen Smalley
2007-05-14 11:06 ` [AppArmor 40/45] AppArmor: all the rest jjohansen
2007-05-14 11:06 ` [AppArmor 41/45] Add AppArmor LSM to security/Makefile jjohansen
2007-05-14 11:06 ` [AppArmor 42/45] AppArmor: add lock subtyping so lockdep does not report false dependencies jjohansen
2007-05-14 11:06 ` [AppArmor 43/45] Switch to vfs_permission() in do_path_lookup() jjohansen
2007-05-14 11:06 ` [AppArmor 44/45] Switch to vfs_permission() in sys_fchdir() jjohansen
2007-05-14 11:06 ` [AppArmor 45/45] Fix file_permission() jjohansen
2007-05-14 13:50 ` [AppArmor 00/45] AppArmor security module overview John Johansen
2007-10-26  6:40 jjohansen
2007-10-26  6:41 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching jjohansen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).