2007-02-05 18:23:13

by Tony Jones

[permalink] [raw]
Subject: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

Introduction
------------

The following are a set of patches the goal of which is to pass vfsmounts
through select portions of the VFS layer sufficient to be visible to the LSM
inode operation hooks.

They are being posted now as a request for comment. Presently the AppArmor
code - being a user of the LSM interface - does not receive the vfsmount
correspoding to an operation and has to employ convoluted and slow mechanisms
in an attempt to determine the vfsmount which are error prone. Therefore these
patches or some variant of them are viewed as a necessary precursor for the
AppArmor code being resubmitted.

It is currently planned to resubmit the AppArmor code to the list in the next
month. We apologise greatly for the silence since the last submission, a
combination of research into different designs, other work pressures and just
not doing the "right thing". Regardless, early discussion and feedback on
the interface changes presented here is appreciated.

Limitations of the current patches
----------------------------------

NULL is passed for the vfsmount from all NFS functions, this is analagous
to the current NULL nameidata for security_inode_permission. NULL is also
passed in certain cases for internal filesystem data which is not visible in
the normal namespace (Reiserfs being one example).

Struct vfsmount is passed to the LSM inode hooks rather than struct nameidata
as the hooks do not require the intent data and also as a few hooks are called
when only a struct file is available.

Possible changes
----------------

A second parameter is now being passed to many functions. One alternative is
to ammend the LSM interface (and struct nameidata) to use struct path instead
but this would be a larger change.

Patches
-------

security-create.diff
Pass struct vfsmount to the inode_create LSM hook.

proc_setattr.diff
Remove redundant check from proc_setattr().

remove_suid.diff
Pass struct file down to remove_suid and children

vfs-notify_change.diff
Add a vfsmount parameter to notify_change()

security-setattr.diff
Pass struct vfsmount to the inode_setattr LSM hook

vfs-mkdir.diff
Add struct vfsmount parameter to vfs_mkdir()

security-mkdir.diff
Pass struct vfsmount to the inode_mkdir LSM hook

vfs-mknod.diff
Add a struct vfsmount parameter to vfs_mknod()

security-mknod.diff
Pass struct vfsmount to the inode_mknod LSM hook

vfs-symlink.diff
Add a struct vfsmount parameter to vfs_symlink()

security-symlink.diff
Pass struct vfsmount to the inode_symlink LSM hook.

security-readlink.diff
Pass struct vfsmount to the inode_readlink LSM hook

vfs-link.diff
Add struct vfsmount parameters to vfs_link()

security-link.diff
Pass struct vfsmount to the inode_link LSM hook

vfs-rmdir.diff
Add a struct vfsmount parameter to vfs_rmdir()

security-rmdir.diff
Pass struct vfsmount to the inode_rmdir LSM hook

vfs-unlink.diff
Add a struct vfsmount parameter to vfs_unlink()

security-unlink.diff
Pass struct vfsmount to the inode_unlink LSM hook

vfs-rename.diff
Add struct vfsmount parameters to vfs_rename()

security-rename.diff
Pass struct vfsmount to the inode_rename LSM hook

vfs-setxattr.diff
Add a struct vfsmount parameter to vfs_setxattr()

security-setxattr.diff
Pass struct vfsmount to the inode_setxattr LSM hook

vfs-getxattr.diff
Add a struct vfsmount parameter to vfs_getxattr()

security-getxattr.diff
Pass struct vfsmount to the inode_getxattr LSM hook

vfs-listxattr.diff
Add a struct vfsmount parameter to vfs_listxattr()

security-listxattr.diff
Pass struct vfsmount to the inode_listxattr LSM hook

vfs-removexattr.diff
Add a struct vfsmount parameter to vfs_removexattr()

security-removexattr.diff
Pass struct vfsmount to the inode_removexattr LSM hook


2007-02-05 18:23:26

by Tony Jones

[permalink] [raw]
Subject: [RFC 1/28] Pass struct vfsmount to the inode_create LSM hook.

Pass struct vfsmount to the inode_create LSM hook.

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -1503,7 +1503,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);
Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2135,7 +2135,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);
}

2007-02-05 18:23:37

by Tony Jones

[permalink] [raw]
Subject: [RFC 2/28] Remove redundant check from proc_setattr().

Remove redundant check from proc_setattr()

notify_change() already calls security_inode_setattr() before
calling iop->setattr.

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/proc/base.c
===================================================================
--- linux-2.6.orig/fs/proc/base.c
+++ linux-2.6/fs/proc/base.c
@@ -344,11 +344,8 @@ static int proc_setattr(struct dentry *d
return -EPERM;

error = inode_change_ok(inode, attr);
- if (!error) {
- error = security_inode_setattr(dentry, attr);
- if (!error)
- error = inode_setattr(inode, attr);
- }
+ if (!error)
+ error = inode_setattr(inode, attr);
return error;
}

2007-02-05 18:23:55

by Tony Jones

[permalink] [raw]
Subject: [RFC 3/28] Pass struct file down to remove_suid and children

Pass struct file down to remove_suid and children

Pass struct path to remove_suid and should_remove_suid instead of
only the dentry. Required by a later patch that adds a struct
vfsmount parameter to notify_change().

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/mm/filemap.c
===================================================================
--- linux-2.6.orig/mm/filemap.c
+++ linux-2.6/mm/filemap.c
@@ -1869,9 +1869,9 @@ repeat:
* if suid or (sgid and xgrp)
* remove privs
*/
-int should_remove_suid(struct dentry *dentry)
+int should_remove_suid(struct path *path)
{
- mode_t mode = dentry->d_inode->i_mode;
+ mode_t mode = path->dentry->d_inode->i_mode;
int kill = 0;

/* suid always must be killed */
@@ -1892,20 +1892,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);

if (unlikely(kill))
- return __remove_suid(dentry, kill);
+ return __remove_suid(path, kill);

return 0;
}
@@ -2266,7 +2266,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;

Index: linux-2.6/fs/ntfs/file.c
===================================================================
--- linux-2.6.orig/fs/ntfs/file.c
+++ linux-2.6/fs/ntfs/file.c
@@ -2162,7 +2162,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);
Index: linux-2.6/fs/reiserfs/file.c
===================================================================
--- linux-2.6.orig/fs/reiserfs/file.c
+++ linux-2.6/fs/reiserfs/file.c
@@ -1353,7 +1353,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;

Index: linux-2.6/fs/splice.c
===================================================================
--- linux-2.6.orig/fs/splice.c
+++ linux-2.6/fs/splice.c
@@ -844,7 +844,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;

@@ -890,10 +890,10 @@ generic_file_splice_write(struct pipe_in
ssize_t ret;
int err;

- err = should_remove_suid(out->f_path.dentry);
+ err = should_remove_suid(&out->f_path);
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;
Index: linux-2.6/fs/xfs/linux-2.6/xfs_lrw.c
===================================================================
--- linux-2.6.orig/fs/xfs/linux-2.6/xfs_lrw.c
+++ linux-2.6/fs/xfs/linux-2.6/xfs_lrw.c
@@ -805,7 +805,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)) {
xfs_iunlock(xip, iolock);
goto out_unlock_mutex;
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1678,9 +1678,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 should_remove_suid(struct dentry *);
-extern int remove_suid(struct dentry *);
+extern int __remove_suid(struct path *, int);
+extern int should_remove_suid(struct path *);
+extern int remove_suid(struct path *);
extern void remove_dquot_ref(struct super_block *, int, struct list_head *);

extern void __insert_inode_hash(struct inode *, unsigned long hashval);
Index: linux-2.6/mm/filemap_xip.c
===================================================================
--- linux-2.6.orig/mm/filemap_xip.c
+++ linux-2.6/mm/filemap_xip.c
@@ -379,7 +379,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;

Index: linux-2.6/mm/shmem.c
===================================================================
--- linux-2.6.orig/mm/shmem.c
+++ linux-2.6/mm/shmem.c
@@ -1447,7 +1447,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;

Index: linux-2.6/fs/ocfs2/file.c
===================================================================
--- linux-2.6.orig/fs/ocfs2/file.c
+++ linux-2.6/fs/ocfs2/file.c
@@ -1035,13 +1035,13 @@ out:
return ret;
}

-static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
+static int ocfs2_prepare_inode_for_write(struct path *path,
loff_t *ppos,
size_t count,
int appending)
{
int ret = 0, meta_level = appending;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = path->dentry->d_inode;
u32 clusters;
loff_t newsize, saved_pos;

@@ -1067,7 +1067,7 @@ static int ocfs2_prepare_inode_for_write
* inode. There's also the dinode i_size state which
* can be lost via setattr during extending writes (we
* set inode->i_size at the end of a write. */
- if (should_remove_suid(dentry)) {
+ if (should_remove_suid(path)) {
if (meta_level == 0) {
ocfs2_meta_unlock(inode, meta_level);
meta_level = 1;
@@ -1176,7 +1176,7 @@ static ssize_t ocfs2_file_aio_write(stru
goto out;
}

- ret = ocfs2_prepare_inode_for_write(filp->f_path.dentry, &iocb->ki_pos,
+ ret = ocfs2_prepare_inode_for_write(&filp->f_path, &iocb->ki_pos,
iocb->ki_left, appending);
if (ret < 0) {
mlog_errno(ret);
@@ -1239,7 +1239,7 @@ static ssize_t ocfs2_file_splice_write(s
goto out;
}

- ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, ppos, len, 0);
+ ret = ocfs2_prepare_inode_for_write(&out->f_path, ppos, len, 0);
if (ret < 0) {
mlog_errno(ret);
goto out_unlock;

2007-02-05 18:24:20

by Tony Jones

[permalink] [raw]
Subject: [RFC 5/28] Pass struct vfsmount to the inode_setattr LSM hook

Pass struct vfsmount to the inode_setattr LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/attr.c
===================================================================
--- linux-2.6.orig/fs/attr.c
+++ linux-2.6/fs/attr.c
@@ -145,13 +145,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))
Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2226,11 +2226,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;

2007-02-05 18:24:47

by Tony Jones

[permalink] [raw]
Subject: [RFC 8/28] Add a struct vfsmount parameter to vfs_mknod()

Add a struct vfsmount parameter to vfs_mknod()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/ecryptfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/inode.c
+++ linux-2.6/fs/ecryptfs/inode.c
@@ -552,11 +552,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);
Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -1837,7 +1837,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);

@@ -1889,11 +1890,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;
Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -1189,7 +1189,7 @@ 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, NULL, iap->ia_mode, rdev);
break;
default:
printk("nfsd: bad file type %o in nfsd_create\n", type);
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -980,7 +980,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 *);
Index: linux-2.6/net/unix/af_unix.c
===================================================================
--- linux-2.6.orig/net/unix/af_unix.c
+++ linux-2.6/net/unix/af_unix.c
@@ -808,7 +808,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);

2007-02-05 18:25:09

by Tony Jones

[permalink] [raw]
Subject: [RFC 11/28] Pass struct vfsmount to the inode_symlink LSM hook.

Pass struct vfsmount to the inode_symlink LSM hook.

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2196,7 +2196,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;

Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2161,7 +2161,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);
}

2007-02-05 18:25:31

by Tony Jones

[permalink] [raw]
Subject: [RFC 13/28] Add struct vfsmount parameters to vfs_link()

Add struct vfsmount parameters to vfs_link()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2250,7 +2250,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;
@@ -2328,7 +2328,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);
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -982,7 +982,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 *);
Index: linux-2.6/fs/ecryptfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/inode.c
+++ linux-2.6/fs/ecryptfs/inode.c
@@ -403,19 +403,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);
Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -1527,7 +1527,7 @@ 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, NULL, dirp, dnew, NULL);
if (!host_err) {
if (EX_ISSYNC(ffhp->fh_export)) {
err = nfserrno(nfsd_sync_dir(ddir));

2007-02-05 18:26:07

by Tony Jones

[permalink] [raw]
Subject: [RFC 18/28] Pass struct vfsmount to the inode_unlink LSM hook

Pass struct vfsmount to the inode_unlink LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2102,7 +2102,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);
}
Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
}
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2156,11 +2156,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);

2007-02-05 18:26:25

by Tony Jones

[permalink] [raw]
Subject: [RFC 15/28] Add a struct vfsmount parameter to vfs_rmdir()

Add a struct vfsmount parameter to vfs_rmdir()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/ecryptfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/inode.c
+++ linux-2.6/fs/ecryptfs/inode.c
@@ -534,14 +534,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);
Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2006,7 +2006,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);

@@ -2070,7 +2070,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);
Index: linux-2.6/fs/nfsd/nfs4recover.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs4recover.c
+++ linux-2.6/fs/nfsd/nfs4recover.c
@@ -275,7 +275,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, NULL);
mutex_unlock(&dir->d_inode->i_mutex);
return status;
}
Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -1694,7 +1694,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
#endif
host_err = vfs_unlink(dirp, rdentry);
} else { /* It's RMDIR */
- host_err = vfs_rmdir(dirp, rdentry);
+ host_err = vfs_rmdir(dirp, rdentry, NULL);
}

dput(rdentry);
Index: linux-2.6/fs/reiserfs/xattr.c
===================================================================
--- linux-2.6.orig/fs/reiserfs/xattr.c
+++ linux-2.6/fs/reiserfs/xattr.c
@@ -823,7 +823,7 @@ int reiserfs_delete_xattrs(struct inode
if (dir->d_inode->i_nlink <= 2) {
root = get_xa_root(inode->i_sb);
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 {
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -983,7 +983,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 *);

2007-02-05 18:26:54

by Tony Jones

[permalink] [raw]
Subject: [RFC 22/28] Pass struct vfsmount to the inode_setxattr LSM hook

Pass struct vfsmount to the inode_setxattr LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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)
Index: linux-2.6/security/commoncap.c
===================================================================
--- linux-2.6.orig/security/commoncap.c
+++ linux-2.6/security/commoncap.c
@@ -191,8 +191,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) &&
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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)
{
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2264,7 +2264,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;
@@ -2324,7 +2326,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;
Index: linux-2.6/fs/xattr.c
===================================================================
--- linux-2.6.orig/fs/xattr.c
+++ linux-2.6/fs/xattr.c
@@ -81,7 +81,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;
@@ -89,7 +89,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,

2007-02-05 18:27:05

by Tony Jones

[permalink] [raw]
Subject: [RFC 21/28] Add a struct vfsmount parameter to vfs_setxattr()

Add a struct vfsmount parameter to vfs_setxattr()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -415,7 +415,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
goto out;
}

- error = vfs_setxattr(dentry, key, buf, len, 0);
+ error = vfs_setxattr(dentry, NULL, key, buf, len, 0);
out:
kfree(buf);
return error;
@@ -1969,7 +1969,7 @@ 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, NULL, name, value, size,0);
else {
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
error = 0;
Index: linux-2.6/fs/xattr.c
===================================================================
--- linux-2.6.orig/fs/xattr.c
+++ linux-2.6/fs/xattr.c
@@ -70,8 +70,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;
@@ -194,8 +194,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;
@@ -222,7 +222,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;
}
@@ -237,7 +237,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;
}
@@ -252,7 +252,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;
}
@@ -270,7 +270,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;
}
Index: linux-2.6/include/linux/xattr.h
===================================================================
--- linux-2.6.orig/include/linux/xattr.h
+++ linux-2.6/include/linux/xattr.h
@@ -42,7 +42,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);

2007-02-05 18:27:31

by Tony Jones

[permalink] [raw]
Subject: [RFC 25/28] Add a struct vfsmount parameter to vfs_listxattr()

Add a struct vfsmount parameter to vfs_listxattr()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/xattr.c
===================================================================
--- linux-2.6.orig/fs/xattr.c
+++ linux-2.6/fs/xattr.c
@@ -144,18 +144,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;
}
@@ -425,7 +428,7 @@ sys_flistxattr(int fd, char __user *list
f = fget(fd);
if (!f)
return error;
- error = listxattr(f->f_path.dentry, list, size);
+ error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
fput(f);
return error;
}
Index: linux-2.6/include/linux/xattr.h
===================================================================
--- linux-2.6.orig/include/linux/xattr.h
+++ linux-2.6/include/linux/xattr.h
@@ -42,7 +42,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 *);

2007-02-05 18:26:51

by Tony Jones

[permalink] [raw]
Subject: [RFC 23/28] Add a struct vfsmount parameter to vfs_getxattr()

Add a struct vfsmount parameter to vfs_getxattr()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -382,7 +382,7 @@ static ssize_t nfsd_getxattr(struct dent
{
ssize_t buflen;

- buflen = vfs_getxattr(dentry, key, NULL, 0);
+ buflen = vfs_getxattr(dentry, NULL, key, NULL, 0);
if (buflen <= 0)
return buflen;

@@ -390,7 +390,7 @@ static ssize_t nfsd_getxattr(struct dent
if (!*buf)
return -ENOMEM;

- return vfs_getxattr(dentry, key, *buf, buflen);
+ return vfs_getxattr(dentry, NULL, key, *buf, buflen);
}
#endif

Index: linux-2.6/fs/xattr.c
===================================================================
--- linux-2.6.orig/fs/xattr.c
+++ linux-2.6/fs/xattr.c
@@ -107,7 +107,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;
@@ -279,7 +280,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;
@@ -299,7 +301,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;
@@ -322,7 +324,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;
}
@@ -337,7 +339,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,
f = fget(fd);
if (!f)
return error;
- 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;
}
Index: linux-2.6/include/linux/xattr.h
===================================================================
--- linux-2.6.orig/include/linux/xattr.h
+++ linux-2.6/include/linux/xattr.h
@@ -40,7 +40,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);

2007-02-05 18:27:53

by Tony Jones

[permalink] [raw]
Subject: [RFC 28/28] Pass struct vfsmount to the inode_removexattr LSM hook

Pass struct vfsmount to the inode_removexattr LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/xattr.c
===================================================================
--- linux-2.6.orig/fs/xattr.c
+++ linux-2.6/fs/xattr.c
@@ -178,7 +178,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;

Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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)
Index: linux-2.6/security/commoncap.c
===================================================================
--- linux-2.6.orig/security/commoncap.c
+++ linux-2.6/security/commoncap.c
@@ -201,7 +201,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) &&
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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) &&
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2363,7 +2363,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,

2007-02-05 18:28:11

by Tony Jones

[permalink] [raw]
Subject: [RFC 26/28] Pass struct vfsmount to the inode_listxattr LSM hook

Pass struct vfsmount to the inode_listxattr LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/xattr.c
===================================================================
--- linux-2.6.orig/fs/xattr.c
+++ linux-2.6/fs/xattr.c
@@ -150,7 +150,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;
Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
}
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2358,7 +2358,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);
}

2007-02-05 18:28:30

by Tony Jones

[permalink] [raw]
Subject: [RFC 27/28] Add a struct vfsmount parameter to vfs_removexattr()

Add a struct vfsmount parameter to vfs_removexattr()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -1974,7 +1974,7 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
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, NULL, name);
if (error == -ENODATA)
error = 0;
}
Index: linux-2.6/fs/xattr.c
===================================================================
--- linux-2.6.orig/fs/xattr.c
+++ linux-2.6/fs/xattr.c
@@ -166,7 +166,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;
@@ -437,7 +437,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];
@@ -448,7 +448,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
@@ -460,7 +460,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;
}
@@ -474,7 +474,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;
}
@@ -491,7 +491,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;
}
Index: linux-2.6/include/linux/xattr.h
===================================================================
--- linux-2.6.orig/include/linux/xattr.h
+++ linux-2.6/include/linux/xattr.h
@@ -46,7 +46,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);

2007-02-05 18:29:08

by Tony Jones

[permalink] [raw]
Subject: [RFC 24/28] Pass struct vfsmount to the inode_getxattr LSM hook

Pass struct vfsmount to the inode_getxattr LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/xattr.c
===================================================================
--- linux-2.6.orig/fs/xattr.c
+++ linux-2.6/fs/xattr.c
@@ -117,7 +117,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;

Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
}
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2352,7 +2352,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);
}

2007-02-05 18:30:52

by Tony Jones

[permalink] [raw]
Subject: [RFC 20/28] Pass struct vfsmount to the inode_rename LSM hook

Pass struct vfsmount to the inode_rename LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2398,7 +2398,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;

@@ -2432,7 +2433,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;

Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
}
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2197,8 +2197,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);
}

2007-02-05 18:31:05

by Tony Jones

[permalink] [raw]
Subject: [RFC 19/28] Add struct vfsmount parameters to vfs_rename()

Add struct vfsmount parameters to vfs_rename()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/ecryptfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/inode.c
+++ linux-2.6/fs/ecryptfs/inode.c
@@ -590,19 +590,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);
Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2382,7 +2382,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;
@@ -2425,7 +2426,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;
@@ -2453,7 +2455,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);
@@ -2482,9 +2485,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,
@@ -2556,8 +2561,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:
Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -1620,7 +1620,7 @@ 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, NULL, tdir, ndentry, NULL);
if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
host_err = nfsd_sync_dir(tdentry);
if (!host_err)
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -985,7 +985,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.

2007-02-05 18:31:30

by Tony Jones

[permalink] [raw]
Subject: [RFC 16/28] Pass struct vfsmount to the inode_rmdir LSM hook

Pass struct vfsmount to the inode_rmdir LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2023,7 +2023,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)
Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
}
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2178,7 +2178,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);
}

2007-02-05 18:26:06

by Tony Jones

[permalink] [raw]
Subject: [RFC 17/28] Add a struct vfsmount parameter to vfs_unlink()

Add a struct vfsmount parameter to vfs_unlink()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/ecryptfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/inode.c
+++ linux-2.6/fs/ecryptfs/inode.c
@@ -445,10 +445,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;
Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2086,7 +2086,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);

@@ -2150,7 +2150,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);
}
Index: linux-2.6/fs/nfsd/nfs4recover.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs4recover.c
+++ linux-2.6/fs/nfsd/nfs4recover.c
@@ -260,7 +260,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, NULL);
mutex_unlock(&dir->d_inode->i_mutex);
return status;
}
Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -1692,7 +1692,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, NULL);
} else { /* It's RMDIR */
host_err = vfs_rmdir(dirp, rdentry, NULL);
}
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -984,7 +984,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 *);

/*
Index: linux-2.6/ipc/mqueue.c
===================================================================
--- linux-2.6.orig/ipc/mqueue.c
+++ linux-2.6/ipc/mqueue.c
@@ -747,7 +747,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);

2007-02-05 18:24:44

by Tony Jones

[permalink] [raw]
Subject: [RFC 9/28] Pass struct vfsmount to the inode_mknod LSM hook

Pass struct vfsmount to the inode_mknod LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -1851,7 +1851,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;

Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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 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;
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2177,11 +2177,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;

2007-02-05 18:32:17

by Tony Jones

[permalink] [raw]
Subject: [RFC 14/28] Pass struct vfsmount to the inode_link LSM hook

Pass the struct vfsmounts to the inode_link LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2275,7 +2275,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;

Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
}
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2141,11 +2141,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);

2007-02-05 18:32:51

by Tony Jones

[permalink] [raw]
Subject: [RFC 12/28] Pass struct vfsmount to the inode_readlink LSM hook

Pass struct vfsmount to the inode_readlink LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/stat.c
===================================================================
--- linux-2.6.orig/fs/stat.c
+++ linux-2.6/fs/stat.c
@@ -307,7 +307,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);
Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
}
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2196,7 +2196,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);
}

2007-02-05 18:33:19

by Tony Jones

[permalink] [raw]
Subject: [RFC 10/28] Add a struct vfsmount parameter to vfs_symlink()

Add a struct vfsmount parameter to vfs_symlink()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/ecryptfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/inode.c
+++ linux-2.6/fs/ecryptfs/inode.c
@@ -462,6 +462,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;
@@ -470,6 +471,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,
@@ -479,7 +481,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)
Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -2185,7 +2185,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);

@@ -2231,7 +2232,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);
Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -1463,11 +1463,12 @@ 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, NULL,
+ 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, NULL, path, mode);

if (!host_err) {
if (EX_ISSYNC(fhp->fh_export))
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -981,7 +981,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 *);

2007-02-05 18:34:06

by Tony Jones

[permalink] [raw]
Subject: [RFC 7/28] Pass struct vfsmount to the inode_mkdir LSM hook

Pass struct vfsmount to the inode_mkdir LSM hook

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -1928,7 +1928,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;

Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/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;
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/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;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2166,7 +2166,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);
}

2007-02-05 18:34:43

by Tony Jones

[permalink] [raw]
Subject: [RFC 6/28] Add struct vfsmount parameter to vfs_mkdir()

Add struct vfsmount parameter to vfs_mkdir()

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/ecryptfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/inode.c
+++ linux-2.6/fs/ecryptfs/inode.c
@@ -501,11 +501,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);
Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -1916,7 +1916,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);

@@ -1960,7 +1961,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);
Index: linux-2.6/fs/nfsd/nfs4recover.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs4recover.c
+++ linux-2.6/fs/nfsd/nfs4recover.c
@@ -156,7 +156,7 @@ 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, NULL, S_IRWXU);
out_put:
dput(dentry);
out_unlock:
Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -1183,7 +1183,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, NULL, iap->ia_mode);
break;
case S_IFCHR:
case S_IFBLK:
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -979,7 +979,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 *);

2007-02-05 18:34:57

by Tony Jones

[permalink] [raw]
Subject: [RFC 4/28] Add a vfsmount parameter to notify_change()

Add a vfsmount parameter to notify_change()

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.

The kernel nfsd also doesn't have the necessary context for client
requests. We cannot put it under any pathname based policy, and
also set vfsmount to NULL there.

The next patch passes the vfsmount to the inode_setattr LSM hook.

Signed-off-by: Tony Jones <[email protected]>
Signed-off-by: Andreas Gruenbacher <[email protected]>

Index: linux-2.6/fs/attr.c
===================================================================
--- linux-2.6.orig/fs/attr.c
+++ linux-2.6/fs/attr.c
@@ -101,7 +101,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;
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1457,8 +1457,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);
@@ -1605,7 +1605,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));
Index: linux-2.6/fs/ecryptfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/inode.c
+++ linux-2.6/fs/ecryptfs/inode.c
@@ -856,12 +856,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) {
@@ -876,7 +878,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;
Index: linux-2.6/fs/fat/file.c
===================================================================
--- linux-2.6.orig/fs/fat/file.c
+++ linux-2.6/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;

Index: linux-2.6/fs/hpfs/namei.c
===================================================================
--- linux-2.6.orig/fs/hpfs/namei.c
+++ linux-2.6/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;
Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/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, NULL, iap);
err = nfserrno(host_err);
fh_unlock(fhp);
}
@@ -896,7 +896,7 @@ static void kill_suid(struct dentry *den
ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;

mutex_lock(&dentry->d_inode->i_mutex);
- notify_change(dentry, &ia);
+ notify_change(dentry, NULL, &ia);
mutex_unlock(&dentry->d_inode->i_mutex);
}

Index: linux-2.6/fs/open.c
===================================================================
--- linux-2.6.orig/fs/open.c
+++ linux-2.6/fs/open.c
@@ -194,8 +194,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;
@@ -212,7 +212,7 @@ int do_truncate(struct dentry *dentry, l
}

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;
}
@@ -267,7 +267,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);

@@ -319,7 +319,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:
@@ -519,7 +520,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:
@@ -554,7 +555,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:
@@ -568,7 +569,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;
@@ -597,7 +599,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;
@@ -611,7 +613,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;
@@ -631,7 +633,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;
@@ -645,7 +647,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;
@@ -664,7 +666,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;
Index: linux-2.6/fs/reiserfs/xattr.c
===================================================================
--- linux-2.6.orig/fs/reiserfs/xattr.c
+++ linux-2.6/fs/reiserfs/xattr.c
@@ -527,7 +527,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;

@@ -867,7 +867,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;
@@ -919,7 +919,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:
Index: linux-2.6/fs/sysfs/file.c
===================================================================
--- linux-2.6.orig/fs/sysfs/file.c
+++ linux-2.6/fs/sysfs/file.c
@@ -526,7 +526,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);
Index: linux-2.6/fs/utimes.c
===================================================================
--- linux-2.6.orig/fs/utimes.c
+++ linux-2.6/fs/utimes.c
@@ -62,7 +62,7 @@ asmlinkage long sys_utime(char __user *
goto dput_and_out;
}
mutex_lock(&inode->i_mutex);
- error = notify_change(nd.dentry, &newattrs);
+ error = notify_change(nd.dentry, nd.mnt, &newattrs);
mutex_unlock(&inode->i_mutex);
dput_and_out:
path_release(&nd);
@@ -115,7 +115,7 @@ long do_utimes(int dfd, char __user *fil
goto dput_and_out;
}
mutex_lock(&inode->i_mutex);
- error = notify_change(nd.dentry, &newattrs);
+ error = notify_change(nd.dentry, nd.mnt, &newattrs);
mutex_unlock(&inode->i_mutex);
dput_and_out:
path_release(&nd);
Index: linux-2.6/mm/filemap.c
===================================================================
--- linux-2.6.orig/mm/filemap.c
+++ linux-2.6/mm/filemap.c
@@ -1897,7 +1897,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)
Index: linux-2.6/fs/exec.c
===================================================================
--- linux-2.6.orig/fs/exec.c
+++ linux-2.6/fs/exec.c
@@ -1534,7 +1534,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);
Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c
+++ linux-2.6/fs/namei.c
@@ -1580,7 +1580,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)
Index: linux-2.6/mm/tiny-shmem.c
===================================================================
--- linux-2.6.orig/mm/tiny-shmem.c
+++ linux-2.6/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;

2007-02-05 18:44:28

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

Just FYI: Al was very opposed to the idea of passing the vfsmount to
the vfs_ helpers, so you should discuss this with him.

Looking at the actual patches I see you're lazy in a lot of places.
Please make sure that when you introduce a vfsmount argument somewhere
that it is _always_ passed and not just when it's conveniant. Yes, that's
more work, but then again if you're not consistant anyone half-serious
will laught at a security model using this infrasturcture.

2007-02-05 18:58:39

by Trond Myklebust

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Mon, 2007-02-05 at 18:44 +0000, Christoph Hellwig wrote:
> Just FYI: Al was very opposed to the idea of passing the vfsmount to
> the vfs_ helpers, so you should discuss this with him.
>
> Looking at the actual patches I see you're lazy in a lot of places.
> Please make sure that when you introduce a vfsmount argument somewhere
> that it is _always_ passed and not just when it's conveniant. Yes, that's
> more work, but then again if you're not consistant anyone half-serious
> will laught at a security model using this infrasturcture.

nfsd in particular tends to be a bit lazy about passing around vfsmount
info. Forcing it to do so should not be hard since the vfsmount is
already cached in the "struct export" (which can be found using the
filehandle). It will take a bit of re-engineering in order to pass that
information around inside the nfsd code, though.

Note also that it might be nice to enforce the vfsmount argument by
replacing the existing dentry parameters with a struct path instead of
adding an extra reference to the vfsmount to existing functions.

Cheers,
Trond

2007-02-05 19:02:34

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Mon, Feb 05, 2007 at 10:58:26AM -0800, Trond Myklebust wrote:
> On Mon, 2007-02-05 at 18:44 +0000, Christoph Hellwig wrote:
> > Just FYI: Al was very opposed to the idea of passing the vfsmount to
> > the vfs_ helpers, so you should discuss this with him.
> >
> > Looking at the actual patches I see you're lazy in a lot of places.
> > Please make sure that when you introduce a vfsmount argument somewhere
> > that it is _always_ passed and not just when it's conveniant. Yes, that's
> > more work, but then again if you're not consistant anyone half-serious
> > will laught at a security model using this infrasturcture.
>
> nfsd in particular tends to be a bit lazy about passing around vfsmount
> info. Forcing it to do so should not be hard since the vfsmount is
> already cached in the "struct export" (which can be found using the
> filehandle). It will take a bit of re-engineering in order to pass that
> information around inside the nfsd code, though.

I actually have a patch to fix that. It's part of a bigger series
that's not quite ready, but I hope to finish all of it this month.

> Note also that it might be nice to enforce the vfsmount argument by
> replacing the existing dentry parameters with a struct path instead of
> adding an extra reference to the vfsmount to existing functions.

That definitly sounds like a good idea, independent of whether we want
to pass the vfsmount in more places or not.

2007-02-05 19:08:28

by Chris Wright

[permalink] [raw]
Subject: Re: [RFC 2/28] Remove redundant check from proc_setattr().

* Tony Jones ([email protected]) wrote:
> Remove redundant check from proc_setattr()

Indeed, I'll take that straight away.

thanks,
-chris

2007-02-05 19:08:40

by Chris Wright

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

* Trond Myklebust ([email protected]) wrote:
> On Mon, 2007-02-05 at 18:44 +0000, Christoph Hellwig wrote:
> > Just FYI: Al was very opposed to the idea of passing the vfsmount to
> > the vfs_ helpers, so you should discuss this with him.
> >
> > Looking at the actual patches I see you're lazy in a lot of places.
> > Please make sure that when you introduce a vfsmount argument somewhere
> > that it is _always_ passed and not just when it's conveniant. Yes, that's
> > more work, but then again if you're not consistant anyone half-serious
> > will laught at a security model using this infrasturcture.
>
> nfsd in particular tends to be a bit lazy about passing around vfsmount
> info. Forcing it to do so should not be hard since the vfsmount is
> already cached in the "struct export" (which can be found using the
> filehandle). It will take a bit of re-engineering in order to pass that
> information around inside the nfsd code, though.

Yeah, last time I looked at that it was always available, just a bit ugly
to go digging for the vfsmount.

2007-02-05 19:27:03

by Casey Schaufler

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks


--- Tony Jones <[email protected]> wrote:

> Introduction
> ------------
>
> The following are a set of patches the goal of which
> is to pass vfsmounts
> through select portions of the VFS layer sufficient
> to be visible to the LSM
> inode operation hooks.



>
> They are being posted now as a request for comment.
> Presently the AppArmor
> code - being a user of the LSM interface - does not
> receive the vfsmount
> correspoding to an operation and has to employ
> convoluted and slow mechanisms
> in an attempt to determine the vfsmount which are
> error prone.

Would it be possible for you to describe those
methods? Perhaps there is a better way to go
about getting the information you need without
introducing this level of change.



Casey Schaufler
[email protected]

2007-02-05 19:39:22

by Arjan van de Ven

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks


>
> Would it be possible for you to describe those
> methods? Perhaps there is a better way to go
> about getting the information you need without
> introducing this level of change.

the code did a full walk of the vfsmounts to find a match. Entirely
horrid!

There is no problem with such a medium-severity level change as long as
it's the right thing... in Linux we mostly try to solve problems the
right way rather than adding workarounds on both sides of an interface
after all ;-)


--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org

2007-02-05 19:43:00

by Chris Wright

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

* Casey Schaufler ([email protected]) wrote:
> > They are being posted now as a request for comment.
> > Presently the AppArmor
> > code - being a user of the LSM interface - does not
> > receive the vfsmount
> > correspoding to an operation and has to employ
> > convoluted and slow mechanisms
> > in an attempt to determine the vfsmount which are
> > error prone.
>
> Would it be possible for you to describe those
> methods? Perhaps there is a better way to go
> about getting the information you need without
> introducing this level of change.

It's not really worth describing, since it's not acceptable in upstream.
But it basically cycles vfsmnts and looks for matches to guess which
part of the tree the dentry is in. This kind of change (or perhaps
straight to struct path) is definitely needed from AA.

2007-02-05 20:23:28

by Casey Schaufler

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks


--- Chris Wright <[email protected]> wrote:


> It's not really worth describing, since it's not
> acceptable in upstream.
> But it basically cycles vfsmnts and looks for
> matches to guess which
> part of the tree the dentry is in.

Yick. Indeed, that would be bad.

> This kind of change (or perhaps
> straight to struct path) is definitely
> needed from AA.

It is certainly tempting to suggest that the
path struct scheme would be better. The only
argument against it that I see is the kind
of changes you'd have to make to existing code.
It's not even a matter of having to make
changes, just which changes you make.


Casey Schaufler
[email protected]

2007-02-06 00:44:22

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Monday 05 February 2007 10:44, Christoph Hellwig wrote:
> Just FYI: Al was very opposed to the idea of passing the vfsmount to
> the vfs_ helpers, so you should discuss this with him.

The vfs_ helper functions are the ones calling the lsm hooks in many cases.
Any lsm that makes pathname based decisions will need both the dentry and
vfsmount for figuring out a file's pathname. I don't see a better way of
passing that information to the lsm hooks than passing it through the vfs_
helpers.

Thanks,
Andreas

2007-02-06 02:13:49

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Monday 05 February 2007 10:44, Christoph Hellwig wrote:
> Looking at the actual patches I see you're lazy in a lot of places.
> Please make sure that when you introduce a vfsmount argument somewhere
> that it is _always_ passed and not just when it's conveniant. Yes, that's
> more work, but then again if you're not consistant anyone half-serious
> will laught at a security model using this infrasturcture.

It may appear like laziness, but it's not. Let's look at where we're passing
NULL at the moment:

fs/hpfs/namei.c

In hpfs_unlink, hpfs truncates one of its own inodes through
notify_change(). You definitely don't want any lsms to interfere here,
pathname based or not; hpfs should probably truncate its inode itself
instead. But given that hpfs goes via the vfs, we at least pass NULL
to indicate that this file really has no meaningful paths to it
anymore. (In addition, we don't really have a vfsmount at this
point anymore, and neither would it make sense to pass it there.)

To play more nicely with other lsms, hpfs could mark the inode as
private before attempting the truncate.

fs/reiserfs/xattr.c

The directories an files that reiserfs uses internally to store xattrs
are hanging off ".reiserfs_priv/xattrs" in the filesystem. This part
of the namespace is not accessible or visible from user space though
except through the xattr syscalls.

Reiserfs should probably just mark all its xattr inodes as private in order
to play nicely with other lsms. As far as pathname based lsms are concerned,
pathnames to those fs-internal objects are meaningless though, and so we
pass NULL here.

fs/sysfs/file.c
fs/nfsd/vfs.c and fs/nfsd/nfs4recover.c

For nfsd, the concept of pathnames is a bit peculiar. I'll try to respond to
that separately.

Thanks,
Andreas

2007-02-06 02:30:59

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Monday 05 February 2007 11:50, Chris Wright wrote:
> This kind of change (or perhaps straight to struct path) is definitely
> needed from AA.

I tried struct path; in terms of code size it doesn't seem worth it. We could
get identical code out of it as if we were passing the dentry and vfsmount
individually, with somewhat slimmer looking interfaces, but then we'd have to
create temporary struct path objects in a few places, and accessing either
object would become a bit more verbose (path.dentry instead of dentry, etc.)

See the following thread on linux-kernel, Message-ID
[email protected]:

[RFC] Pack the vfsmount and dentry in nameidata into a struct path

Thanks,
Andreas

2007-02-06 03:21:07

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Monday 05 February 2007 11:02, Christoph Hellwig wrote:
> On Mon, Feb 05, 2007 at 10:58:26AM -0800, Trond Myklebust wrote:
> > On Mon, 2007-02-05 at 18:44 +0000, Christoph Hellwig wrote:
> > > Just FYI: Al was very opposed to the idea of passing the vfsmount to
> > > the vfs_ helpers, so you should discuss this with him.
> > >
> > > Looking at the actual patches I see you're lazy in a lot of places.
> > > Please make sure that when you introduce a vfsmount argument somewhere
> > > that it is _always_ passed and not just when it's conveniant. Yes,
> > > that's more work, but then again if you're not consistant anyone
> > > half-serious will laught at a security model using this infrasturcture.
> >
> > nfsd in particular tends to be a bit lazy about passing around vfsmount
> > info. Forcing it to do so should not be hard since the vfsmount is
> > already cached in the "struct export" (which can be found using the
> > filehandle). It will take a bit of re-engineering in order to pass that
> > information around inside the nfsd code, though.
>
> I actually have a patch to fix that. It's part of a bigger series
> that's not quite ready, but I hope to finish all of it this month.

It's actually not hard to "fix", and nfsd would look a little less weird. But
what would this add, what do pathnames mean in the context of nfsd, and would
nfsd actually become less weird?

On the wire, nfs transmits file handles, not filenames. The file handle
usually contains the inode numbers of the file and the containing directory.

The code in fs/exportfs/expfs.c:find_exported_dentry() shows that fh_verify()
should return a dentry that may be connected or not, depending on the export
options and whether it's a file or directory. Together with the vfsmount from
the svc_export, we could compute a pathname.

But there is no way to tell different hardlinks to the same inode in the same
directory from each other (both the file and directory inode are the same),
and depending on the export options, we may or may not be able to distinguish
different hardlinks across directories.

If the nohide or crossmnt export options are used, we might run into similar
aliasing issues with mounts (I'm not sure about this).

So we could compute pathnames, but they wouldn't be very meaningful. Instead
of going that way, it seems more reasonable to not do pathname based access
control for the kernel kernel nfsd at all. Passing NULL as the vfsmounts does
that. With a properly configured nfsd, the areas that remote users could
access would still be well confined.

The focus with this whole pathname based security stuff really is to be able
to better confine local processes. The kernel nfsd is a kernel thread, and as
such, confining it from a security point of view cannot really work, anyway.

> > Note also that it might be nice to enforce the vfsmount argument by
> > replacing the existing dentry parameters with a struct path instead of
> > adding an extra reference to the vfsmount to existing functions.
>
> That definitly sounds like a good idea, independent of whether we want
> to pass the vfsmount in more places or not.

Note that you can still pass a NULL vfsmount in a struct path.

Thanks,
Andreas

2007-02-06 08:52:01

by Trond Myklebust

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Mon, 2007-02-05 at 19:20 -0800, Andreas Gruenbacher wrote:
> On Monday 05 February 2007 11:02, Christoph Hellwig wrote:
> > On Mon, Feb 05, 2007 at 10:58:26AM -0800, Trond Myklebust wrote:
> > > On Mon, 2007-02-05 at 18:44 +0000, Christoph Hellwig wrote:
> > > > Just FYI: Al was very opposed to the idea of passing the vfsmount to
> > > > the vfs_ helpers, so you should discuss this with him.
> > > >
> > > > Looking at the actual patches I see you're lazy in a lot of places.
> > > > Please make sure that when you introduce a vfsmount argument somewhere
> > > > that it is _always_ passed and not just when it's conveniant. Yes,
> > > > that's more work, but then again if you're not consistant anyone
> > > > half-serious will laught at a security model using this infrasturcture.
> > >
> > > nfsd in particular tends to be a bit lazy about passing around vfsmount
> > > info. Forcing it to do so should not be hard since the vfsmount is
> > > already cached in the "struct export" (which can be found using the
> > > filehandle). It will take a bit of re-engineering in order to pass that
> > > information around inside the nfsd code, though.
> >
> > I actually have a patch to fix that. It's part of a bigger series
> > that's not quite ready, but I hope to finish all of it this month.
>
> It's actually not hard to "fix", and nfsd would look a little less weird. But
> what would this add, what do pathnames mean in the context of nfsd, and would
> nfsd actually become less weird?
>
> On the wire, nfs transmits file handles, not filenames. The file handle
> usually contains the inode numbers of the file and the containing directory.
>
> The code in fs/exportfs/expfs.c:find_exported_dentry() shows that fh_verify()
> should return a dentry that may be connected or not, depending on the export
> options and whether it's a file or directory. Together with the vfsmount from
> the svc_export, we could compute a pathname.
>
> But there is no way to tell different hardlinks to the same inode in the same
> directory from each other (both the file and directory inode are the same),
> and depending on the export options, we may or may not be able to distinguish
> different hardlinks across directories.

Who cares? There is no way to export a partial directory, and in any
case the subtree_check crap is borken beyond repair (see cross-directory
renames which lead to actual changes to the filehandle - broken, broken,
broken!!!!).

> If the nohide or crossmnt export options are used, we might run into similar
> aliasing issues with mounts (I'm not sure about this).

Wrong. Those create new export points since you are crossing into a
different filesystem.

> So we could compute pathnames, but they wouldn't be very meaningful. Instead
> of going that way, it seems more reasonable to not do pathname based access
> control for the kernel kernel nfsd at all. Passing NULL as the vfsmounts does
> that. With a properly configured nfsd, the areas that remote users could
> access would still be well confined.

Huh? Even if you don't pass in a vfsmount, you _still_ need to pass in a
super_block. Inodes are only unique per filesystem.
In fact, on an ideal NFS export, there is no ambiguity between the two
(see above comment about subtree_check) since the entire filesystem will
be exported.

> The focus with this whole pathname based security stuff really is to be able
> to better confine local processes. The kernel nfsd is a kernel thread, and as
> such, confining it from a security point of view cannot really work, anyway.
>
> > > Note also that it might be nice to enforce the vfsmount argument by
> > > replacing the existing dentry parameters with a struct path instead of
> > > adding an extra reference to the vfsmount to existing functions.
> >
> > That definitly sounds like a good idea, independent of whether we want
> > to pass the vfsmount in more places or not.
>
> Note that you can still pass a NULL vfsmount in a struct path.

...but we will have Dick Cheney track you down and shoot you if you do.
The point is that you only have to check _one_ argument (the
initialisation of the struct path) instead of having a check for every
function argument in the vfs.

Trond

2007-02-06 09:47:27

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Mon, Feb 05, 2007 at 07:20:35PM -0800, Andreas Gruenbacher wrote:
> It's actually not hard to "fix", and nfsd would look a little less weird. But
> what would this add, what do pathnames mean in the context of nfsd, and would
> nfsd actually become less weird?

It's not actually a pathname we care about, but a vfsmount + dentry
combo. That one means as much in nfsd as elsewhere. We want nfsd
to obey r/o or noatime mount flags if /export/foo is exported with them
but /foo not. Even better would be to change nfsd so it creates it's
own non-visible vfsmount for the filesystems it exports..

> But there is no way to tell different hardlinks to the same inode in the same
> directory from each other (both the file and directory inode are the same),
> and depending on the export options, we may or may not be able to distinguish
> different hardlinks across directories.

This doesn't matter. hardlinks are per definition on the same vfsmount.

> If the nohide or crossmnt export options are used, we might run into similar
> aliasing issues with mounts (I'm not sure about this).

no, we won't.

2007-02-06 09:48:12

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Tue, Feb 06, 2007 at 12:51:52AM -0800, Trond Myklebust wrote:
> Who cares? There is no way to export a partial directory, and in any
> case the subtree_check crap is borken beyond repair (see cross-directory
> renames which lead to actual changes to the filehandle - broken, broken,
> broken!!!!).

It's getting a little oftopic for this thread, but is there a chance we
could just kill that crap after a resonable deprecation period?

2007-02-06 09:52:39

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Mon, Feb 05, 2007 at 06:13:26PM -0800, Andreas Gruenbacher wrote:
> On Monday 05 February 2007 10:44, Christoph Hellwig wrote:
> > Looking at the actual patches I see you're lazy in a lot of places.
> > Please make sure that when you introduce a vfsmount argument somewhere
> > that it is _always_ passed and not just when it's conveniant. Yes, that's
> > more work, but then again if you're not consistant anyone half-serious
> > will laught at a security model using this infrasturcture.
>
> It may appear like laziness, but it's not. Let's look at where we're passing
> NULL at the moment:

You know, I've tracked a lot of this down previously when I submitted patches
to add vfsmount arguments to the vfs_ helpers, just to get tought by Al
that this is a bad idea :)

> fs/hpfs/namei.c
>
> In hpfs_unlink, hpfs truncates one of its own inodes through
> notify_change(). You definitely don't want any lsms to interfere here,
> pathname based or not; hpfs should probably truncate its inode itself
> instead. But given that hpfs goes via the vfs, we at least pass NULL
> to indicate that this file really has no meaningful paths to it
> anymore. (In addition, we don't really have a vfsmount at this
> point anymore, and neither would it make sense to pass it there.)
>
> To play more nicely with other lsms, hpfs could mark the inode as
> private before attempting the truncate.

The right fix would be to not go through the vfs. Or even better to
remove the utter hack. See my previous patch on this subject and the
discussion started on it.

> fs/reiserfs/xattr.c
>
> The directories an files that reiserfs uses internally to store xattrs
> are hanging off ".reiserfs_priv/xattrs" in the filesystem. This part
> of the namespace is not accessible or visible from user space though
> except through the xattr syscalls.
>
> Reiserfs should probably just mark all its xattr inodes as private in order
> to play nicely with other lsms. As far as pathname based lsms are concerned,
> pathnames to those fs-internal objects are meaningless though, and so we
> pass NULL here.

Well, the 100% correct fix would be to rip out the braindead reiserfs
xattr code :)
Of course that's not an option, but reiserfs would be much better of
stop using vfs_rmdir. It really doesn't need most of the checks in there
and should just call into reiserfs_rmdir instead of doing this useless
trip into vfs land.

> fs/sysfs/file.c

> fs/nfsd/vfs.c and fs/nfsd/nfs4recover.c
>
> For nfsd, the concept of pathnames is a bit peculiar. I'll try to respond to
> that separately.

the actually nfsd filehandle code is conceptually trivially fixable,
although with quite a bit of code churn. As mention I'll soon submit
a patch for it. nfs4recover.c is broken beyond repair and should just
be deleted from the tree.

2007-02-06 10:27:09

by NeilBrown

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Tuesday February 6, [email protected] wrote:
> On Mon, Feb 05, 2007 at 07:20:35PM -0800, Andreas Gruenbacher wrote:
> > It's actually not hard to "fix", and nfsd would look a little less weird. But
> > what would this add, what do pathnames mean in the context of nfsd, and would
> > nfsd actually become less weird?
>
> It's not actually a pathname we care about, but a vfsmount + dentry
> combo. That one means as much in nfsd as elsewhere. We want nfsd
> to obey r/o or noatime mount flags if /export/foo is exported with them
> but /foo not. Even better would be to change nfsd so it creates it's
> own non-visible vfsmount for the filesystems it exports..

What would be the benefit of having private non-visible vfsmounts?
Sounds like a recipe for confusion?

It is possible that mountd might start doing bind-mounts to create the
'pseudo filesystem' thing for NFSv4, but they would be very visible
(under /var/lib/nfs/v4root or something). So having it's own vfsmount
might make sense, but I don't get 'non-visible'.

NeilBrown

2007-02-06 10:32:22

by NeilBrown

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Tuesday February 6, [email protected] wrote:
> On Tue, Feb 06, 2007 at 12:51:52AM -0800, Trond Myklebust wrote:
> > Who cares? There is no way to export a partial directory, and in any
> > case the subtree_check crap is borken beyond repair (see cross-directory
> > renames which lead to actual changes to the filehandle - broken, broken,
> > broken!!!!).
>
> It's getting a little oftopic for this thread, but is there a chance we
> could just kill that crap after a resonable deprecation period?

Probably. A couple of years?
nfs-utils 1.1.0 is due to stop subtree_check from being the default.
After that is released, the next kernel can start printing warnings
that it might stop working in a couple of years.

NeilBrown

2007-02-06 10:37:40

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Tue, Feb 06, 2007 at 09:26:14PM +1100, Neil Brown wrote:
> What would be the benefit of having private non-visible vfsmounts?
> Sounds like a recipe for confusion?
>
> It is possible that mountd might start doing bind-mounts to create the
> 'pseudo filesystem' thing for NFSv4, but they would be very visible
> (under /var/lib/nfs/v4root or something). So having it's own vfsmount
> might make sense, but I don't get 'non-visible'.

It would allow creating an exported tree without interferance with
the local visible tree. Note that the local visible tree isn't
global anymore either, and this allows to adjust what's exported
through nfsd throug a specific interface instead of needing to
get into nfsd namespace through some way. Think of listing the
actually exported devices in /etc/exports instead of the indirection
through fstab aswell.

2007-02-06 13:00:37

by Stephen Smalley

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Mon, 2007-02-05 at 18:13 -0800, Andreas Gruenbacher wrote:
> On Monday 05 February 2007 10:44, Christoph Hellwig wrote:
> > Looking at the actual patches I see you're lazy in a lot of places.
> > Please make sure that when you introduce a vfsmount argument somewhere
> > that it is _always_ passed and not just when it's conveniant. Yes, that's
> > more work, but then again if you're not consistant anyone half-serious
> > will laught at a security model using this infrasturcture.
>
> It may appear like laziness, but it's not. Let's look at where we're passing
> NULL at the moment:
>
> fs/hpfs/namei.c
>
> In hpfs_unlink, hpfs truncates one of its own inodes through
> notify_change(). You definitely don't want any lsms to interfere here,
> pathname based or not; hpfs should probably truncate its inode itself
> instead. But given that hpfs goes via the vfs, we at least pass NULL
> to indicate that this file really has no meaningful paths to it
> anymore. (In addition, we don't really have a vfsmount at this
> point anymore, and neither would it make sense to pass it there.)
>
> To play more nicely with other lsms, hpfs could mark the inode as
> private before attempting the truncate.
>
> fs/reiserfs/xattr.c
>
> The directories an files that reiserfs uses internally to store xattrs
> are hanging off ".reiserfs_priv/xattrs" in the filesystem. This part
> of the namespace is not accessible or visible from user space though
> except through the xattr syscalls.
>
> Reiserfs should probably just mark all its xattr inodes as private in order
> to play nicely with other lsms. As far as pathname based lsms are concerned,
> pathnames to those fs-internal objects are meaningless though, and so we
> pass NULL here.

That should be handled by the current marking of reiserfs xattr inodes
with S_PRIVATE and the tests for IS_PRIVATE in include/linux/security.h
(and in one instance, within SELinux itself).

--
Stephen Smalley
National Security Agency

2007-02-06 14:52:40

by Tetsuo Handa

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

Tony Jones wrote:
> The following are a set of patches the goal of which is to pass vfsmounts
> through select portions of the VFS layer sufficient to be visible to the LSM
> inode operation hooks.
I was looking forward to these patches for so long.

Chris Wright wrote:
> This kind of change (or perhaps
> straight to struct path) is definitely
> needed from AA.
Not only AppArmor, but also TOMOYO Linux needs these patches.

TOMOYO Linux is a pathname based access control patch like AppArmor.
http://lwn.net/Articles/165132/
I have been asked "Why not use LSM?" and the answer is always
"I can't, for VFS helper functions and LSM functions don't receive vfsmount."
and I am manually patching locations that call VFS helper functions.

But if these Tony's patches are accepted in upstream,
TOMOYO Linux would be able to use LSM.
I think these patches are also useful for auditing functions, for
auditing logs will be able to include absolute pathname
instead of partial pathname.
I think most people want access logs in the form of pathnames
rather than security labels.

2007-02-07 08:55:38

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Tuesday 06 February 2007 04:55, Stephen Smalley wrote:
> On Mon, 2007-02-05 at 18:13 -0800, Andreas Gruenbacher wrote:
> > Reiserfs should probably just mark all its xattr inodes as private in
> > order to play nicely with other lsms. As far as pathname based lsms are
> > concerned, pathnames to those fs-internal objects are meaningless though,
> > and so we pass NULL here.
>
> That should be handled by the current marking of reiserfs xattr inodes
> with S_PRIVATE and the tests for IS_PRIVATE in include/linux/security.h
> (and in one instance, within SELinux itself).

Reiserfs currently only marks the ".reiserfs_priv" directory as private, but
not the files below it -- how about the attached patch to fix that?

Andreas


Attachments:
(No filename) (734.00 B)
reiserfs-mark-xattrs-private.diff (3.40 kB)
Download all attachments

2007-02-07 09:04:32

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Tuesday 06 February 2007 01:52, Christoph Hellwig wrote:
> On Mon, Feb 05, 2007 at 06:13:26PM -0800, Andreas Gruenbacher wrote:
> > On Monday 05 February 2007 10:44, Christoph Hellwig wrote:
> > > Looking at the actual patches I see you're lazy in a lot of places.
> > > Please make sure that when you introduce a vfsmount argument somewhere
> > > that it is _always_ passed and not just when it's conveniant. Yes,
> > > that's more work, but then again if you're not consistant anyone
> > > half-serious will laught at a security model using this infrasturcture.
> >
> > It may appear like laziness, but it's not. Let's look at where we're
> > passing NULL at the moment:
>
> You know, I've tracked a lot of this down previously when I submitted
> patches to add vfsmount arguments to the vfs_ helpers, just to get tought
> by Al that this is a bad idea :)

Hmmm, I really would like to know how else we could get at that information in
the lsm hooks then.

Andreas

2007-02-07 09:25:42

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

Hi Trond,

On Tuesday 06 February 2007 00:51, Trond Myklebust wrote:
> > But there is no way to tell different hardlinks to the same inode in the
> > same directory from each other (both the file and directory inode are the
> > same), and depending on the export options, we may or may not be able to
> > distinguish different hardlinks across directories.
>
> Who cares? There is no way to export a partial directory, and in any
> case the subtree_check crap is borken beyond repair (see cross-directory
> renames which lead to actual changes to the filehandle - broken, broken,
> broken!!!!).

I do agree that the directory inode number would better not be part of the
filehandle. In this thread I'm trying to argue why trying to compute
pathnames based on nfs file handles makes no sense though, and that the sane
thing is not to even try.

> > If the nohide or crossmnt export options are used, we might run into
> > similar aliasing issues with mounts (I'm not sure about this).
>
> Wrong. Those create new export points since you are crossing into a
> different filesystem.

I'm glad to be proven wrong here. Pathnames for nfs remain meaningless even
without mount point aliasing, though.

> > So we could compute pathnames, but they wouldn't be very meaningful.
> > Instead of going that way, it seems more reasonable to not do pathname
> > based access control for the kernel kernel nfsd at all. Passing NULL as
> > the vfsmounts does that. With a properly configured nfsd, the areas that
> > remote users could access would still be well confined.
>
> Huh? Even if you don't pass in a vfsmount, you _still_ need to pass in a
> super_block. Inodes are only unique per filesystem.

No worries, the super_block is not hanging off struct vfsmount, it's hanging
off struct dentry.

Thanks,
Andreas

2007-02-07 09:58:35

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Tuesday 06 February 2007 01:47, Christoph Hellwig wrote:
> On Mon, Feb 05, 2007 at 07:20:35PM -0800, Andreas Gruenbacher wrote:
> > It's actually not hard to "fix", and nfsd would look a little less weird.
> > But what would this add, what do pathnames mean in the context of nfsd,
> > and would nfsd actually become less weird?
>
> It's not actually a pathname we care about, but a vfsmount + dentry
> combo. That one means as much in nfsd as elsewhere. We want nfsd
> to obey r/o or noatime mount flags if /export/foo is exported with them
> but /foo not.

This assumes that you can discover from the file handle which export it
belongs to. And right, this can be done using the fsid export option. Okay,
I'm now convinced that passing the vfsmounts from the svc_export to the vfs_
helpers is good at least for *something*. I'll update the patches.

> > But there is no way to tell different hardlinks to the same inode in the
> > same directory from each other (both the file and directory inode are the
> > same), and depending on the export options, we may or may not be able to
> > distinguish different hardlinks across directories.
>
> This doesn't matter. hardlinks are per definition on the same vfsmount.

Hardlinks are per definition on the same filesystem. This doesn't mean that
you can't have two filehandles for the same file but with different
vfsmounts -- you can have the same file visible in multiple locations, each
with their own vfsmount.

Thanks,
Andreas

2007-02-07 12:11:44

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Wed, Feb 07, 2007 at 01:58:15AM -0800, Andreas Gruenbacher wrote:
> > It's not actually a pathname we care about, but a vfsmount + dentry
> > combo. That one means as much in nfsd as elsewhere. We want nfsd
> > to obey r/o or noatime mount flags if /export/foo is exported with them
> > but /foo not.
>
> This assumes that you can discover from the file handle which export it
> belongs to. And right, this can be done using the fsid export option. Okay,
> I'm now convinced that passing the vfsmounts from the svc_export to the vfs_
> helpers is good at least for *something*. I'll update the patches.

As I mentioned before I have a big patchset reworking this area, so please
wait a week or two for me two finish it instead of creating lots of rejects.

> > This doesn't matter. hardlinks are per definition on the same vfsmount.
>
> Hardlinks are per definition on the same filesystem. This doesn't mean that
> you can't have two filehandles for the same file but with different
> vfsmounts -- you can have the same file visible in multiple locations, each
> with their own vfsmount.

Sure, but that doesn't matter here. Exports are per-vfsmount, and
each export has the vfsmount stored in it. So we know which of the
vfsmount we want before we even resolve the dentry. And yes, if
I have /export/foo mounted with option but /foo now I want those
options to apply to the nfs export. Note that we actually have another
little bug in this area currently: if you export two different
patch that have the same underlying filesystems they actually do get
the same file handle unless using fsid=. We probably need to put
a check into svc_export_parse so that we don't export the same
device twice without using fsid=.


2007-02-07 15:36:25

by Chris Wright

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

* Andreas Gruenbacher ([email protected]) wrote:
> Reiserfs currently only marks the ".reiserfs_priv" directory as private, but
> not the files below it -- how about the attached patch to fix that?

I don't think that's right. Look at ->create or ->lookup. Both of those
properly set the private flag. This patch looks like a step backwards,
sprinkling the init in so many places.

> Fix reiserfs xattrs for selinux
>
> Mark all inodes used for reiserfs xattrs as private so that selinux
> (or any other LSM) will not try to mediate access to the files and
> directories used as the xattr backing store. The xattr operations
> are already protected through the xattr LSM hooks.
>
> There is no real reason for having reiserfs_mark_inode_private --
> remove it and directly mark the inodes as private.
>
> Signed-off-by: Andreas Gruenbacher <[email protected]>
> Cc: Jeff Mahoney <[email protected]>
>
> Index: b/fs/reiserfs/xattr.c
> ===================================================================
> --- a/fs/reiserfs/xattr.c
> +++ b/fs/reiserfs/xattr.c
> @@ -79,6 +79,7 @@ static struct dentry *create_xa_root(str
> dput(privroot);
> return ERR_PTR(err);
> }
> + xaroot->d_inode->i_flags |= S_PRIVATE;

Already handled in the above ->mkdir

> REISERFS_SB(sb)->xattr_root = dget(xaroot);
> }
>
> @@ -108,6 +109,7 @@ static struct dentry *__get_xa_root(stru
> goto out;
> }
>
> + xaroot->d_inode->i_flags |= S_PRIVATE;

Already handled during xa_root creation

> REISERFS_SB(s)->xattr_root = dget(xaroot);
>
> out:
> @@ -183,6 +185,7 @@ static struct dentry *open_xa_dir(const
> return ERR_PTR(-ENODATA);
> }
> }
> + xadir->d_inode->i_flags |= S_PRIVATE;

Already handled in lookup or mkdir

> dput(xaroot);
> return xadir;
> @@ -235,6 +238,8 @@ static struct dentry *get_xa_file_dentry
> dput(xadir);
> if (err)
> xafile = ERR_PTR(err);
> + else
> + xafile->d_inode->i_flags |= S_PRIVATE;

Already handled in lookup or create

> return xafile;
> }
>
> @@ -715,6 +720,7 @@ __reiserfs_xattr_del(struct dentry *xadi
> err = -ENODATA;
> goto out_file;
> }
Already handled in lookup

etc...

2007-02-07 16:12:04

by Stephen Smalley

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Wed, 2007-02-07 at 07:43 -0800, Chris Wright wrote:
> * Andreas Gruenbacher ([email protected]) wrote:
> > Reiserfs currently only marks the ".reiserfs_priv" directory as private, but
> > not the files below it -- how about the attached patch to fix that?
>
> I don't think that's right. Look at ->create or ->lookup. Both of those
> properly set the private flag. This patch looks like a step backwards,
> sprinkling the init in so many places.

Yes, I thought that this was already covered by the existing inheritance
of the private flag from the parent directory.

On a separate note, I believe that the current problem with using
reiserfs and selinux is just that reiserfs hasn't been updated to call
security_inode_init_security() and set the security xattr when creating
a new file; see ext3 or jfs for an example. But I don't know of anyone
using reiserfs with selinux presently.

--
Stephen Smalley
National Security Agency

2007-02-07 16:26:08

by Jeff Mahoney

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Chris Wright wrote:
> * Andreas Gruenbacher ([email protected]) wrote:
>> Reiserfs currently only marks the ".reiserfs_priv" directory as private, but
>> not the files below it -- how about the attached patch to fix that?
>
> I don't think that's right. Look at ->create or ->lookup. Both of those
> properly set the private flag. This patch looks like a step backwards,
> sprinkling the init in so many places.

Yeah, this is exactly what happens. The flag is purposely only set once,
and then is inherited up the tree. I'm fine removing the helper
function, but the inheritance should be working fine. Have you seen
behavior that is contrary?

- -Jeff

>> Fix reiserfs xattrs for selinux
>>
>> Mark all inodes used for reiserfs xattrs as private so that selinux
>> (or any other LSM) will not try to mediate access to the files and
>> directories used as the xattr backing store. The xattr operations
>> are already protected through the xattr LSM hooks.
>>
>> There is no real reason for having reiserfs_mark_inode_private --
>> remove it and directly mark the inodes as private.
>>
>> Signed-off-by: Andreas Gruenbacher <[email protected]>
>> Cc: Jeff Mahoney <[email protected]>
>>
>> Index: b/fs/reiserfs/xattr.c
>> ===================================================================
>> --- a/fs/reiserfs/xattr.c
>> +++ b/fs/reiserfs/xattr.c
>> @@ -79,6 +79,7 @@ static struct dentry *create_xa_root(str
>> dput(privroot);
>> return ERR_PTR(err);
>> }
>> + xaroot->d_inode->i_flags |= S_PRIVATE;
>
> Already handled in the above ->mkdir
>
>> REISERFS_SB(sb)->xattr_root = dget(xaroot);
>> }
>>
>> @@ -108,6 +109,7 @@ static struct dentry *__get_xa_root(stru
>> goto out;
>> }
>>
>> + xaroot->d_inode->i_flags |= S_PRIVATE;
>
> Already handled during xa_root creation
>
>> REISERFS_SB(s)->xattr_root = dget(xaroot);
>>
>> out:
>> @@ -183,6 +185,7 @@ static struct dentry *open_xa_dir(const
>> return ERR_PTR(-ENODATA);
>> }
>> }
>> + xadir->d_inode->i_flags |= S_PRIVATE;
>
> Already handled in lookup or mkdir
>
>> dput(xaroot);
>> return xadir;
>> @@ -235,6 +238,8 @@ static struct dentry *get_xa_file_dentry
>> dput(xadir);
>> if (err)
>> xafile = ERR_PTR(err);
>> + else
>> + xafile->d_inode->i_flags |= S_PRIVATE;
>
> Already handled in lookup or create
>
>> return xafile;
>> }
>>
>> @@ -715,6 +720,7 @@ __reiserfs_xattr_del(struct dentry *xadi
>> err = -ENODATA;
>> goto out_file;
>> }
> Already handled in lookup
>
> etc...


- --
Jeff Mahoney
SUSE Labs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFFyf2MLPWxlyuTD7IRAnjYAJ40js54LOzv+xMqgSnbfeq6DIvJEACeIWhu
9QuXzrKspwXbh8qSx0o/tK8=
=rvqJ
-----END PGP SIGNATURE-----

2007-02-07 19:56:56

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Wednesday 07 February 2007 08:25, Jeff Mahoney wrote:
> Chris Wright wrote:
> > * Andreas Gruenbacher ([email protected]) wrote:
> >> Reiserfs currently only marks the ".reiserfs_priv" directory as private,
> >> but not the files below it -- how about the attached patch to fix that?
> >
> > I don't think that's right. Look at ->create or ->lookup. Both of those
> > properly set the private flag. This patch looks like a step backwards,
> > sprinkling the init in so many places.
>
> Yeah, this is exactly what happens. The flag is purposely only set once,
> and then is inherited up the tree.

That's much better. I take back the patch; sorry I overlooked that.

Thanks,
Andreas

2007-02-12 18:32:56

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [RFC 0/28] Patches to pass vfsmount to LSM inode security hooks

On Tue, Feb 06, 2007 at 10:37:37AM +0000, Christoph Hellwig wrote:
> On Tue, Feb 06, 2007 at 09:26:14PM +1100, Neil Brown wrote:
> > What would be the benefit of having private non-visible vfsmounts?
> > Sounds like a recipe for confusion?
> >
> > It is possible that mountd might start doing bind-mounts to create the
> > 'pseudo filesystem' thing for NFSv4, but they would be very visible
> > (under /var/lib/nfs/v4root or something).
> > So having it's own vfsmount might make sense, but I don't get
> > 'non-visible'.

> It would allow creating an exported tree without interferance with
> the local visible tree. Note that the local visible tree isn't
> global anymore either, and this allows to adjust what's exported
> through nfsd throug a specific interface instead of needing to
> get into nfsd namespace through some way.

What would this interface look like? Would it be a user<->kernel
interface, or a user<->mountd interface?

Tentatively what I was thinking of was having mountd fork off its own
namespace, use /etc/exports to construct a mount tree there, then pass
that mount tree down to the kernel using the existing exports cache
channel. Name resolution in svc_export_parse should be done in mountd's
namespace, so I think this works.

> Think of listing the actually exported devices in /etc/exports instead
> of the indirection through fstab aswell.

Hm. We'd have to add mount options to /etc/exports too if we were going
to do that, right?

--b.