[patch 09/15] security: pass path to inode_setattr

From: Miklos Szeredi
Date: Thu May 29 2008 - 09:53:44 EST


From: Miklos Szeredi <mszeredi@xxxxxxx>

In the inode_setattr() security operation and related functions pass
the path (vfsmount + dentry) instead of the dentry. AppArmor will need
this.

Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxx>
---
fs/attr.c | 9 +++++----
fs/fat/file.c | 2 +-
fs/namei.c | 2 +-
fs/open.c | 17 +++++++++--------
include/linux/fs.h | 4 ++--
include/linux/security.h | 9 ++++-----
mm/filemap.c | 14 ++++----------
security/dummy.c | 2 +-
security/security.c | 6 +++---
security/selinux/hooks.c | 5 +++--
security/smack/smack_lsm.c | 6 +++---
11 files changed, 36 insertions(+), 40 deletions(-)

Index: linux-2.6/fs/attr.c
===================================================================
--- linux-2.6.orig/fs/attr.c 2008-05-29 12:20:15.000000000 +0200
+++ linux-2.6/fs/attr.c 2008-05-29 12:20:56.000000000 +0200
@@ -101,8 +101,9 @@ int inode_setattr(struct inode * inode,
}
EXPORT_SYMBOL(inode_setattr);

-int notify_change(struct dentry * dentry, struct iattr * attr)
+int notify_change(struct path *path, struct iattr *attr)
{
+ struct dentry *dentry = path->dentry;
struct inode *inode = dentry->d_inode;
mode_t mode = inode->i_mode;
int error;
@@ -165,13 +166,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(path, 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(path, attr);
if (!error) {
if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
@@ -195,7 +196,7 @@ int path_setattr(struct path *path, stru
int error = mnt_want_write(path->mnt);

if (!error) {
- error = notify_change(path->dentry, attr);
+ error = notify_change(path, attr);
mnt_drop_write(path->mnt);
}

Index: linux-2.6/fs/open.c
===================================================================
--- linux-2.6.orig/fs/open.c 2008-05-29 12:20:49.000000000 +0200
+++ linux-2.6/fs/open.c 2008-05-29 12:20:56.000000000 +0200
@@ -197,16 +197,17 @@ out:

/*
* do_truncate - truncate (or extend) an inode
- * @dentry: the dentry to truncate
+ * @path: the path of the file to truncate
* @length: the new length
* @time_attrs: file times to be updated (e.g. ATTR_MTIME|ATTR_CTIME)
* @filp: an open file or NULL (see file_truncate() as well)
*/
-int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+int do_truncate(struct path *path, loff_t length, unsigned int time_attrs,
struct file *filp)
{
int err;
struct iattr newattrs;
+ struct inode *inode = path->dentry->d_inode;

/* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
if (length < 0)
@@ -220,11 +221,11 @@ int do_truncate(struct dentry *dentry, l
}

/* Remove suid/sgid on truncate too */
- newattrs.ia_valid |= should_remove_suid(dentry);
+ newattrs.ia_valid |= should_remove_suid(path->dentry);

- mutex_lock(&dentry->d_inode->i_mutex);
- err = notify_change(dentry, &newattrs);
- mutex_unlock(&dentry->d_inode->i_mutex);
+ mutex_lock(&inode->i_mutex);
+ err = notify_change(path, &newattrs);
+ mutex_unlock(&inode->i_mutex);
return err;
}

@@ -236,7 +237,7 @@ int do_truncate(struct dentry *dentry, l
*/
int file_truncate(struct file *filp, loff_t length, unsigned int time_attrs)
{
- return do_truncate(filp->f_path.dentry, length, time_attrs, filp);
+ return do_truncate(&filp->f_path, length, time_attrs, filp);
}

static long do_sys_truncate(const char __user * path, loff_t length)
@@ -290,7 +291,7 @@ static long do_sys_truncate(const char _
error = locks_verify_truncate(inode, NULL, length);
if (!error) {
DQUOT_INIT(inode);
- error = do_truncate(nd.path.dentry, length, 0, NULL);
+ error = do_truncate(&nd.path, length, 0, NULL);
}

put_write_and_out:
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h 2008-05-29 12:20:51.000000000 +0200
+++ linux-2.6/include/linux/fs.h 2008-05-29 12:20:56.000000000 +0200
@@ -1628,7 +1628,7 @@ static inline int break_lease(struct ino

/* fs/open.c */

-extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
+extern int do_truncate(struct path *, loff_t start, unsigned int time_attrs,
struct file *filp);
extern int file_truncate(struct file *filp, loff_t start,
unsigned int time_attrs);
@@ -1785,7 +1785,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 path *, struct iattr *);
extern int path_setattr(struct path *, struct iattr *);
extern int generic_permission(struct inode *, int,
int (*check_acl)(struct inode *, int));
Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h 2008-05-29 12:20:55.000000000 +0200
+++ linux-2.6/include/linux/security.h 2008-05-29 12:20:56.000000000 +0200
@@ -413,7 +413,7 @@ static inline void security_free_mnt_opt
* call to notify_change is performed from several locations, whenever
* 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.
+ * @path contains the path to the file.
* @attr is the iattr structure containing the new file attributes.
* Return 0 if permission is granted.
* @inode_getattr:
@@ -1368,7 +1368,7 @@ 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);
- int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
+ int (*inode_setattr) (struct path *path, struct iattr *attr);
int (*inode_getattr) (struct path *path);
void (*inode_delete) (struct inode *inode);
int (*inode_setxattr) (struct dentry *dentry, const char *name,
@@ -1640,7 +1640,7 @@ int security_inode_rename(struct path *o
int security_inode_readlink(struct dentry *dentry);
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask);
-int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
+int security_inode_setattr(struct path *path, struct iattr *attr);
int security_inode_getattr(struct path *path);
void security_inode_delete(struct inode *inode);
int security_inode_setxattr(struct dentry *dentry, const char *name,
@@ -2035,8 +2035,7 @@ static inline int security_inode_permiss
return 0;
}

-static inline int security_inode_setattr(struct dentry *dentry,
- struct iattr *attr)
+static inline int security_inode_setattr(struct path *path, struct iattr *attr)
{
return 0;
}
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c 2008-05-29 12:20:55.000000000 +0200
+++ linux-2.6/security/dummy.c 2008-05-29 12:20:56.000000000 +0200
@@ -348,7 +348,7 @@ 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 path *path, struct iattr *iattr)
{
return 0;
}
Index: linux-2.6/security/security.c
===================================================================
--- linux-2.6.orig/security/security.c 2008-05-29 12:20:55.000000000 +0200
+++ linux-2.6/security/security.c 2008-05-29 12:20:56.000000000 +0200
@@ -471,11 +471,11 @@ int security_inode_permission(struct ino
return security_ops->inode_permission(inode, mask);
}

-int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+int security_inode_setattr(struct path *path, struct iattr *attr)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
return 0;
- return security_ops->inode_setattr(dentry, attr);
+ return security_ops->inode_setattr(path, attr);
}
EXPORT_SYMBOL_GPL(security_inode_setattr);

Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c 2008-05-29 12:20:55.000000000 +0200
+++ linux-2.6/security/selinux/hooks.c 2008-05-29 12:20:56.000000000 +0200
@@ -2579,11 +2579,12 @@ static int selinux_inode_permission(stru
open_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 path *path, struct iattr *iattr)
{
+ struct dentry *dentry = path->dentry;
int rc;

- rc = secondary_ops->inode_setattr(dentry, iattr);
+ rc = secondary_ops->inode_setattr(path, iattr);
if (rc)
return rc;

Index: linux-2.6/security/smack/smack_lsm.c
===================================================================
--- linux-2.6.orig/security/smack/smack_lsm.c 2008-05-29 12:20:55.000000000 +0200
+++ linux-2.6/security/smack/smack_lsm.c 2008-05-29 12:20:56.000000000 +0200
@@ -534,12 +534,12 @@ static int smack_inode_permission(struct

/**
* smack_inode_setattr - Smack check for setting attributes
- * @dentry: the object
+ * @path: the object
* @iattr: for the force flag
*
* Returns 0 if access is permitted, an error code otherwise
*/
-static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+static int smack_inode_setattr(struct path *path, struct iattr *iattr)
{
/*
* Need to allow for clearing the setuid bit.
@@ -547,7 +547,7 @@ static int smack_inode_setattr(struct de
if (iattr->ia_valid & ATTR_FORCE)
return 0;

- return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
+ return smk_curacc(smk_of_inode(path->dentry->d_inode), MAY_WRITE);
}

/**
Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c 2008-05-29 12:20:56.000000000 +0200
+++ linux-2.6/fs/namei.c 2008-05-29 12:20:56.000000000 +0200
@@ -1691,7 +1691,7 @@ int may_open(struct nameidata *nd, int a
if (!error) {
DQUOT_INIT(inode);

- error = do_truncate(dentry, 0,
+ error = do_truncate(&nd->path, 0,
ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
NULL);
}
Index: linux-2.6/fs/fat/file.c
===================================================================
--- linux-2.6.orig/fs/fat/file.c 2008-05-29 12:20:15.000000000 +0200
+++ linux-2.6/fs/fat/file.c 2008-05-29 12:20:56.000000000 +0200
@@ -99,7 +99,7 @@ int fat_generic_ioctl(struct inode *inod
* out the RO attribute for checking by the security
* module, just because it maps to a file mode.
*/
- err = security_inode_setattr(filp->f_path.dentry, &ia);
+ err = security_inode_setattr(&filp->f_path, &ia);
if (err)
goto up;

Index: linux-2.6/mm/filemap.c
===================================================================
--- linux-2.6.orig/mm/filemap.c 2008-05-29 12:20:51.000000000 +0200
+++ linux-2.6/mm/filemap.c 2008-05-29 12:20:56.000000000 +0200
@@ -1660,14 +1660,6 @@ int should_remove_suid(struct dentry *de
}
EXPORT_SYMBOL(should_remove_suid);

-static int __remove_suid(struct dentry *dentry, int kill)
-{
- struct iattr newattrs;
-
- newattrs.ia_valid = ATTR_FORCE | kill;
- return notify_change(dentry, &newattrs);
-}
-
int file_remove_suid(struct file *file)
{
struct dentry *dentry = file->f_path.dentry;
@@ -1679,8 +1671,10 @@ int file_remove_suid(struct file *file)
return killpriv;
if (killpriv)
error = security_inode_killpriv(dentry);
- if (!error && killsuid)
- error = __remove_suid(dentry, killsuid);
+ if (!error && killsuid) {
+ struct iattr newattrs = {.ia_valid = ATTR_FORCE | killsuid };
+ error = notify_change(&file->f_path, &newattrs);
+ }

return error;
}

--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/