Root/
Source at commit 2604e7f9a98c27be50a0c3ff7503b6a5ea8f6cfe created 12 years 7 months ago. By Maarten ter Huurne, cpufreq_stats: Support runtime changes to frequency table | |
---|---|
1 | /* |
2 | * linux/fs/attr.c |
3 | * |
4 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * changes by Thomas Schoebel-Theuer |
6 | */ |
7 | |
8 | #include <linux/export.h> |
9 | #include <linux/time.h> |
10 | #include <linux/mm.h> |
11 | #include <linux/string.h> |
12 | #include <linux/capability.h> |
13 | #include <linux/fsnotify.h> |
14 | #include <linux/fcntl.h> |
15 | #include <linux/security.h> |
16 | #include <linux/evm.h> |
17 | |
18 | /** |
19 | * inode_change_ok - check if attribute changes to an inode are allowed |
20 | * @inode: inode to check |
21 | * @attr: attributes to change |
22 | * |
23 | * Check if we are allowed to change the attributes contained in @attr |
24 | * in the given inode. This includes the normal unix access permission |
25 | * checks, as well as checks for rlimits and others. |
26 | * |
27 | * Should be called as the first thing in ->setattr implementations, |
28 | * possibly after taking additional locks. |
29 | */ |
30 | int inode_change_ok(const struct inode *inode, struct iattr *attr) |
31 | { |
32 | unsigned int ia_valid = attr->ia_valid; |
33 | |
34 | /* |
35 | * First check size constraints. These can't be overriden using |
36 | * ATTR_FORCE. |
37 | */ |
38 | if (ia_valid & ATTR_SIZE) { |
39 | int error = inode_newsize_ok(inode, attr->ia_size); |
40 | if (error) |
41 | return error; |
42 | } |
43 | |
44 | /* If force is set do it anyway. */ |
45 | if (ia_valid & ATTR_FORCE) |
46 | return 0; |
47 | |
48 | /* Make sure a caller can chown. */ |
49 | if ((ia_valid & ATTR_UID) && |
50 | (!uid_eq(current_fsuid(), inode->i_uid) || |
51 | !uid_eq(attr->ia_uid, inode->i_uid)) && !capable(CAP_CHOWN)) |
52 | return -EPERM; |
53 | |
54 | /* Make sure caller can chgrp. */ |
55 | if ((ia_valid & ATTR_GID) && |
56 | (!uid_eq(current_fsuid(), inode->i_uid) || |
57 | (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) && |
58 | !capable(CAP_CHOWN)) |
59 | return -EPERM; |
60 | |
61 | /* Make sure a caller can chmod. */ |
62 | if (ia_valid & ATTR_MODE) { |
63 | if (!inode_owner_or_capable(inode)) |
64 | return -EPERM; |
65 | /* Also check the setgid bit! */ |
66 | if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : |
67 | inode->i_gid) && !capable(CAP_FSETID)) |
68 | attr->ia_mode &= ~S_ISGID; |
69 | } |
70 | |
71 | /* Check for setting the inode time. */ |
72 | if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) { |
73 | if (!inode_owner_or_capable(inode)) |
74 | return -EPERM; |
75 | } |
76 | |
77 | return 0; |
78 | } |
79 | EXPORT_SYMBOL(inode_change_ok); |
80 | |
81 | /** |
82 | * inode_newsize_ok - may this inode be truncated to a given size |
83 | * @inode: the inode to be truncated |
84 | * @offset: the new size to assign to the inode |
85 | * @Returns: 0 on success, -ve errno on failure |
86 | * |
87 | * inode_newsize_ok must be called with i_mutex held. |
88 | * |
89 | * inode_newsize_ok will check filesystem limits and ulimits to check that the |
90 | * new inode size is within limits. inode_newsize_ok will also send SIGXFSZ |
91 | * when necessary. Caller must not proceed with inode size change if failure is |
92 | * returned. @inode must be a file (not directory), with appropriate |
93 | * permissions to allow truncate (inode_newsize_ok does NOT check these |
94 | * conditions). |
95 | */ |
96 | int inode_newsize_ok(const struct inode *inode, loff_t offset) |
97 | { |
98 | if (inode->i_size < offset) { |
99 | unsigned long limit; |
100 | |
101 | limit = rlimit(RLIMIT_FSIZE); |
102 | if (limit != RLIM_INFINITY && offset > limit) |
103 | goto out_sig; |
104 | if (offset > inode->i_sb->s_maxbytes) |
105 | goto out_big; |
106 | } else { |
107 | /* |
108 | * truncation of in-use swapfiles is disallowed - it would |
109 | * cause subsequent swapout to scribble on the now-freed |
110 | * blocks. |
111 | */ |
112 | if (IS_SWAPFILE(inode)) |
113 | return -ETXTBSY; |
114 | } |
115 | |
116 | return 0; |
117 | out_sig: |
118 | send_sig(SIGXFSZ, current, 0); |
119 | out_big: |
120 | return -EFBIG; |
121 | } |
122 | EXPORT_SYMBOL(inode_newsize_ok); |
123 | |
124 | /** |
125 | * setattr_copy - copy simple metadata updates into the generic inode |
126 | * @inode: the inode to be updated |
127 | * @attr: the new attributes |
128 | * |
129 | * setattr_copy must be called with i_mutex held. |
130 | * |
131 | * setattr_copy updates the inode's metadata with that specified |
132 | * in attr. Noticeably missing is inode size update, which is more complex |
133 | * as it requires pagecache updates. |
134 | * |
135 | * The inode is not marked as dirty after this operation. The rationale is |
136 | * that for "simple" filesystems, the struct inode is the inode storage. |
137 | * The caller is free to mark the inode dirty afterwards if needed. |
138 | */ |
139 | void setattr_copy(struct inode *inode, const struct iattr *attr) |
140 | { |
141 | unsigned int ia_valid = attr->ia_valid; |
142 | |
143 | if (ia_valid & ATTR_UID) |
144 | inode->i_uid = attr->ia_uid; |
145 | if (ia_valid & ATTR_GID) |
146 | inode->i_gid = attr->ia_gid; |
147 | if (ia_valid & ATTR_ATIME) |
148 | inode->i_atime = timespec_trunc(attr->ia_atime, |
149 | inode->i_sb->s_time_gran); |
150 | if (ia_valid & ATTR_MTIME) |
151 | inode->i_mtime = timespec_trunc(attr->ia_mtime, |
152 | inode->i_sb->s_time_gran); |
153 | if (ia_valid & ATTR_CTIME) |
154 | inode->i_ctime = timespec_trunc(attr->ia_ctime, |
155 | inode->i_sb->s_time_gran); |
156 | if (ia_valid & ATTR_MODE) { |
157 | umode_t mode = attr->ia_mode; |
158 | |
159 | if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) |
160 | mode &= ~S_ISGID; |
161 | inode->i_mode = mode; |
162 | } |
163 | } |
164 | EXPORT_SYMBOL(setattr_copy); |
165 | |
166 | int notify_change(struct dentry * dentry, struct iattr * attr) |
167 | { |
168 | struct inode *inode = dentry->d_inode; |
169 | umode_t mode = inode->i_mode; |
170 | int error; |
171 | struct timespec now; |
172 | unsigned int ia_valid = attr->ia_valid; |
173 | |
174 | WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); |
175 | |
176 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) { |
177 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
178 | return -EPERM; |
179 | } |
180 | |
181 | if ((ia_valid & ATTR_SIZE) && IS_I_VERSION(inode)) { |
182 | if (attr->ia_size != inode->i_size) |
183 | inode_inc_iversion(inode); |
184 | } |
185 | |
186 | if ((ia_valid & ATTR_MODE)) { |
187 | umode_t amode = attr->ia_mode; |
188 | /* Flag setting protected by i_mutex */ |
189 | if (is_sxid(amode)) |
190 | inode->i_flags &= ~S_NOSEC; |
191 | } |
192 | |
193 | now = current_fs_time(inode->i_sb); |
194 | |
195 | attr->ia_ctime = now; |
196 | if (!(ia_valid & ATTR_ATIME_SET)) |
197 | attr->ia_atime = now; |
198 | if (!(ia_valid & ATTR_MTIME_SET)) |
199 | attr->ia_mtime = now; |
200 | if (ia_valid & ATTR_KILL_PRIV) { |
201 | attr->ia_valid &= ~ATTR_KILL_PRIV; |
202 | ia_valid &= ~ATTR_KILL_PRIV; |
203 | error = security_inode_need_killpriv(dentry); |
204 | if (error > 0) |
205 | error = security_inode_killpriv(dentry); |
206 | if (error) |
207 | return error; |
208 | } |
209 | |
210 | /* |
211 | * We now pass ATTR_KILL_S*ID to the lower level setattr function so |
212 | * that the function has the ability to reinterpret a mode change |
213 | * that's due to these bits. This adds an implicit restriction that |
214 | * no function will ever call notify_change with both ATTR_MODE and |
215 | * ATTR_KILL_S*ID set. |
216 | */ |
217 | if ((ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) && |
218 | (ia_valid & ATTR_MODE)) |
219 | BUG(); |
220 | |
221 | if (ia_valid & ATTR_KILL_SUID) { |
222 | if (mode & S_ISUID) { |
223 | ia_valid = attr->ia_valid |= ATTR_MODE; |
224 | attr->ia_mode = (inode->i_mode & ~S_ISUID); |
225 | } |
226 | } |
227 | if (ia_valid & ATTR_KILL_SGID) { |
228 | if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { |
229 | if (!(ia_valid & ATTR_MODE)) { |
230 | ia_valid = attr->ia_valid |= ATTR_MODE; |
231 | attr->ia_mode = inode->i_mode; |
232 | } |
233 | attr->ia_mode &= ~S_ISGID; |
234 | } |
235 | } |
236 | if (!(attr->ia_valid & ~(ATTR_KILL_SUID | ATTR_KILL_SGID))) |
237 | return 0; |
238 | |
239 | error = security_inode_setattr(dentry, attr); |
240 | if (error) |
241 | return error; |
242 | |
243 | if (inode->i_op->setattr) |
244 | error = inode->i_op->setattr(dentry, attr); |
245 | else |
246 | error = simple_setattr(dentry, attr); |
247 | |
248 | if (!error) { |
249 | fsnotify_change(dentry, ia_valid); |
250 | evm_inode_post_setattr(dentry, ia_valid); |
251 | } |
252 | |
253 | return error; |
254 | } |
255 | EXPORT_SYMBOL(notify_change); |
256 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9