aboutsummaryrefslogtreecommitdiffstats
path: root/fs/attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/attr.c')
-rw-r--r--fs/attr.c84
1 files changed, 51 insertions, 33 deletions
diff --git a/fs/attr.c b/fs/attr.c
index 0815e93bb487..7ca41811afa1 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -14,35 +14,53 @@
14#include <linux/fcntl.h> 14#include <linux/fcntl.h>
15#include <linux/security.h> 15#include <linux/security.h>
16 16
17/* Taken over from the old code... */ 17/**
18 18 * inode_change_ok - check if attribute changes to an inode are allowed
19/* POSIX UID/GID verification for setting inode attributes. */ 19 * @inode: inode to check
20 * @attr: attributes to change
21 *
22 * Check if we are allowed to change the attributes contained in @attr
23 * in the given inode. This includes the normal unix access permission
24 * checks, as well as checks for rlimits and others.
25 *
26 * Should be called as the first thing in ->setattr implementations,
27 * possibly after taking additional locks.
28 */
20int inode_change_ok(const struct inode *inode, struct iattr *attr) 29int inode_change_ok(const struct inode *inode, struct iattr *attr)
21{ 30{
22 int retval = -EPERM;
23 unsigned int ia_valid = attr->ia_valid; 31 unsigned int ia_valid = attr->ia_valid;
24 32
33 /*
34 * First check size constraints. These can't be overriden using
35 * ATTR_FORCE.
36 */
37 if (ia_valid & ATTR_SIZE) {
38 int error = inode_newsize_ok(inode, attr->ia_size);
39 if (error)
40 return error;
41 }
42
25 /* If force is set do it anyway. */ 43 /* If force is set do it anyway. */
26 if (ia_valid & ATTR_FORCE) 44 if (ia_valid & ATTR_FORCE)
27 goto fine; 45 return 0;
28 46
29 /* Make sure a caller can chown. */ 47 /* Make sure a caller can chown. */
30 if ((ia_valid & ATTR_UID) && 48 if ((ia_valid & ATTR_UID) &&
31 (current_fsuid() != inode->i_uid || 49 (current_fsuid() != inode->i_uid ||
32 attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN)) 50 attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
33 goto error; 51 return -EPERM;
34 52
35 /* Make sure caller can chgrp. */ 53 /* Make sure caller can chgrp. */
36 if ((ia_valid & ATTR_GID) && 54 if ((ia_valid & ATTR_GID) &&
37 (current_fsuid() != inode->i_uid || 55 (current_fsuid() != inode->i_uid ||
38 (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) && 56 (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
39 !capable(CAP_CHOWN)) 57 !capable(CAP_CHOWN))
40 goto error; 58 return -EPERM;
41 59
42 /* Make sure a caller can chmod. */ 60 /* Make sure a caller can chmod. */
43 if (ia_valid & ATTR_MODE) { 61 if (ia_valid & ATTR_MODE) {
44 if (!is_owner_or_cap(inode)) 62 if (!is_owner_or_cap(inode))
45 goto error; 63 return -EPERM;
46 /* Also check the setgid bit! */ 64 /* Also check the setgid bit! */
47 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : 65 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
48 inode->i_gid) && !capable(CAP_FSETID)) 66 inode->i_gid) && !capable(CAP_FSETID))
@@ -52,12 +70,10 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
52 /* Check for setting the inode time. */ 70 /* Check for setting the inode time. */
53 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) { 71 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) {
54 if (!is_owner_or_cap(inode)) 72 if (!is_owner_or_cap(inode))
55 goto error; 73 return -EPERM;
56 } 74 }
57fine: 75
58 retval = 0; 76 return 0;
59error:
60 return retval;
61} 77}
62EXPORT_SYMBOL(inode_change_ok); 78EXPORT_SYMBOL(inode_change_ok);
63 79
@@ -67,14 +83,14 @@ EXPORT_SYMBOL(inode_change_ok);
67 * @offset: the new size to assign to the inode 83 * @offset: the new size to assign to the inode
68 * @Returns: 0 on success, -ve errno on failure 84 * @Returns: 0 on success, -ve errno on failure
69 * 85 *
86 * inode_newsize_ok must be called with i_mutex held.
87 *
70 * inode_newsize_ok will check filesystem limits and ulimits to check that the 88 * inode_newsize_ok will check filesystem limits and ulimits to check that the
71 * new inode size is within limits. inode_newsize_ok will also send SIGXFSZ 89 * new inode size is within limits. inode_newsize_ok will also send SIGXFSZ
72 * when necessary. Caller must not proceed with inode size change if failure is 90 * when necessary. Caller must not proceed with inode size change if failure is
73 * returned. @inode must be a file (not directory), with appropriate 91 * returned. @inode must be a file (not directory), with appropriate
74 * permissions to allow truncate (inode_newsize_ok does NOT check these 92 * permissions to allow truncate (inode_newsize_ok does NOT check these
75 * conditions). 93 * conditions).
76 *
77 * inode_newsize_ok must be called with i_mutex held.
78 */ 94 */
79int inode_newsize_ok(const struct inode *inode, loff_t offset) 95int inode_newsize_ok(const struct inode *inode, loff_t offset)
80{ 96{
@@ -104,17 +120,25 @@ out_big:
104} 120}
105EXPORT_SYMBOL(inode_newsize_ok); 121EXPORT_SYMBOL(inode_newsize_ok);
106 122
107int inode_setattr(struct inode * inode, struct iattr * attr) 123/**
124 * setattr_copy - copy simple metadata updates into the generic inode
125 * @inode: the inode to be updated
126 * @attr: the new attributes
127 *
128 * setattr_copy must be called with i_mutex held.
129 *
130 * setattr_copy updates the inode's metadata with that specified
131 * in attr. Noticably missing is inode size update, which is more complex
132 * as it requires pagecache updates.
133 *
134 * The inode is not marked as dirty after this operation. The rationale is
135 * that for "simple" filesystems, the struct inode is the inode storage.
136 * The caller is free to mark the inode dirty afterwards if needed.
137 */
138void setattr_copy(struct inode *inode, const struct iattr *attr)
108{ 139{
109 unsigned int ia_valid = attr->ia_valid; 140 unsigned int ia_valid = attr->ia_valid;
110 141
111 if (ia_valid & ATTR_SIZE &&
112 attr->ia_size != i_size_read(inode)) {
113 int error = vmtruncate(inode, attr->ia_size);
114 if (error)
115 return error;
116 }
117
118 if (ia_valid & ATTR_UID) 142 if (ia_valid & ATTR_UID)
119 inode->i_uid = attr->ia_uid; 143 inode->i_uid = attr->ia_uid;
120 if (ia_valid & ATTR_GID) 144 if (ia_valid & ATTR_GID)
@@ -135,11 +159,8 @@ int inode_setattr(struct inode * inode, struct iattr * attr)
135 mode &= ~S_ISGID; 159 mode &= ~S_ISGID;
136 inode->i_mode = mode; 160 inode->i_mode = mode;
137 } 161 }
138 mark_inode_dirty(inode);
139
140 return 0;
141} 162}
142EXPORT_SYMBOL(inode_setattr); 163EXPORT_SYMBOL(setattr_copy);
143 164
144int notify_change(struct dentry * dentry, struct iattr * attr) 165int notify_change(struct dentry * dentry, struct iattr * attr)
145{ 166{
@@ -207,13 +228,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
207 if (ia_valid & ATTR_SIZE) 228 if (ia_valid & ATTR_SIZE)
208 down_write(&dentry->d_inode->i_alloc_sem); 229 down_write(&dentry->d_inode->i_alloc_sem);
209 230
210 if (inode->i_op && inode->i_op->setattr) { 231 if (inode->i_op->setattr)
211 error = inode->i_op->setattr(dentry, attr); 232 error = inode->i_op->setattr(dentry, attr);
212 } else { 233 else
213 error = inode_change_ok(inode, attr); 234 error = simple_setattr(dentry, attr);
214 if (!error)
215 error = inode_setattr(inode, attr);
216 }
217 235
218 if (ia_valid & ATTR_SIZE) 236 if (ia_valid & ATTR_SIZE)
219 up_write(&dentry->d_inode->i_alloc_sem); 237 up_write(&dentry->d_inode->i_alloc_sem);