]>
Commit | Line | Data |
---|---|---|
2ae1bebf JR |
1 | -------------------------------------------------------------------- |
2 | This patch adds ACL support for JFS. | |
3 | ||
4 | It requires the xattr+acl-0.8.54 patch from http://acl.bestbits.at/ | |
5 | and the JFS extended attribute patch. | |
6 | ||
7 | This patch was built against linux-2.4.20 + JFS 1.1.1 | |
8 | -------------------------------------------------------------------- | |
9 | diff -Nur linux-2.4.20-xattr/Documentation/Configure.help linux-2.4.20-acl/Documentation/Configure.help | |
10 | --- linux-2.4.20-xattr/Documentation/Configure.help 2003-02-03 14:09:00.000000000 -0600 | |
11 | +++ linux-2.4.20-acl/Documentation/Configure.help 2003-02-03 14:38:41.000000000 -0600 | |
12 | @@ -16218,6 +16218,10 @@ | |
13 | ||
14 | If you do not intend to use the JFS filesystem, say N. | |
15 | ||
16 | +JFS Posix ACL support | |
17 | +CONFIG_JFS_POSIX_ACL | |
18 | + Say Y here for Posix ACL support on JFS. | |
19 | + | |
20 | JFS Debugging | |
21 | CONFIG_JFS_DEBUG | |
22 | If you are experiencing any problems with the JFS filesystem, say | |
23 | diff -Nur linux-2.4.20-xattr/fs/Config.in linux-2.4.20-acl/fs/Config.in | |
24 | --- linux-2.4.20-xattr/fs/Config.in 2003-02-03 14:08:41.000000000 -0600 | |
25 | +++ linux-2.4.20-acl/fs/Config.in 2003-02-03 14:38:41.000000000 -0600 | |
26 | @@ -64,6 +64,7 @@ | |
27 | dep_mbool ' Transparent decompression extension' CONFIG_ZISOFS $CONFIG_ISO9660_FS | |
28 | ||
29 | tristate 'JFS filesystem support' CONFIG_JFS_FS | |
30 | +dep_mbool ' JFS Posix ACL support' CONFIG_JFS_POSIX_ACL $CONFIG_JFS_FS $CONFIG_FS_POSIX_ACL | |
31 | dep_mbool ' JFS debugging' CONFIG_JFS_DEBUG $CONFIG_JFS_FS | |
32 | dep_mbool ' JFS statistics' CONFIG_JFS_STATISTICS $CONFIG_JFS_FS | |
33 | ||
34 | diff -Nur linux-2.4.20-xattr/fs/jfs/Makefile linux-2.4.20-acl/fs/jfs/Makefile | |
35 | --- linux-2.4.20-xattr/fs/jfs/Makefile 2003-02-03 14:37:52.000000000 -0600 | |
36 | +++ linux-2.4.20-acl/fs/jfs/Makefile 2003-02-03 14:38:41.000000000 -0600 | |
37 | @@ -14,6 +14,7 @@ | |
38 | jfs_extent.o symlink.o jfs_metapage.o \ | |
39 | jfs_logmgr.o jfs_txnmgr.o jfs_uniupr.o resize.o xattr.o | |
40 | obj-m := $(O_TARGET) | |
41 | +obj-$(CONFIG_JFS_POSIX_ACL) += acl.o | |
42 | ||
43 | EXTRA_CFLAGS += -D_JFS_4K | |
44 | ||
45 | diff -Nur linux-2.4.20-xattr/fs/jfs/acl.c linux-2.4.20-acl/fs/jfs/acl.c | |
46 | --- linux-2.4.20-xattr/fs/jfs/acl.c 1969-12-31 18:00:00.000000000 -0600 | |
47 | +++ linux-2.4.20-acl/fs/jfs/acl.c 2003-02-03 14:38:41.000000000 -0600 | |
48 | @@ -0,0 +1,308 @@ | |
49 | +/* | |
50 | + * Copyright (c) International Business Machines Corp., 2002 | |
51 | + * Copyright (c) Andreas Gruenbacher, 2001 | |
52 | + * Copyright (c) Linus Torvalds, 1991, 1992 | |
53 | + * | |
54 | + * This program is free software; you can redistribute it and/or modify | |
55 | + * it under the terms of the GNU General Public License as published by | |
56 | + * the Free Software Foundation; either version 2 of the License, or | |
57 | + * (at your option) any later version. | |
58 | + * | |
59 | + * This program is distributed in the hope that it will be useful, | |
60 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
61 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | |
62 | + * the GNU General Public License for more details. | |
63 | + * | |
64 | + * You should have received a copy of the GNU General Public License | |
65 | + * along with this program; if not, write to the Free Software | |
66 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
67 | + */ | |
68 | + | |
69 | +#include <linux/fs.h> | |
70 | +#include "jfs_incore.h" | |
71 | +#include "jfs_xattr.h" | |
72 | +#include "jfs_acl.h" | |
73 | + | |
74 | +struct posix_acl *jfs_get_acl(struct inode *inode, int type) | |
75 | +{ | |
76 | + struct posix_acl *acl; | |
77 | + char *ea_name; | |
78 | + struct jfs_inode_info *ji = JFS_IP(inode); | |
79 | + struct posix_acl **p_acl; | |
80 | + int size; | |
81 | + char *value = NULL; | |
82 | + | |
83 | + switch(type) { | |
84 | + case ACL_TYPE_ACCESS: | |
85 | + ea_name = XATTR_NAME_ACL_ACCESS; | |
86 | + p_acl = &ji->i_acl; | |
87 | + break; | |
88 | + case ACL_TYPE_DEFAULT: | |
89 | + ea_name = XATTR_NAME_ACL_DEFAULT; | |
90 | + p_acl = &ji->i_default_acl; | |
91 | + break; | |
92 | + default: | |
93 | + return ERR_PTR(-EINVAL); | |
94 | + } | |
95 | + | |
96 | + if (*p_acl != JFS_ACL_NOT_CACHED) | |
97 | + return posix_acl_dup(*p_acl); | |
98 | + | |
99 | + size = __jfs_getxattr(inode, ea_name, NULL, 0); | |
100 | + | |
101 | + if (size > 0) { | |
102 | + value = kmalloc(size, GFP_KERNEL); | |
103 | + if (!value) | |
104 | + return ERR_PTR(-ENOMEM); | |
105 | + size = __jfs_getxattr(inode, ea_name, value, size); | |
106 | + } | |
107 | + | |
108 | + if (size < 0) { | |
109 | + if (size == -ENOATTR) { | |
110 | + *p_acl = NULL; | |
111 | + acl = NULL; | |
112 | + } else | |
113 | + acl = ERR_PTR(size); | |
114 | + } else { | |
115 | + acl = posix_acl_from_xattr(value, size); | |
116 | + if (!IS_ERR(acl)) | |
117 | + *p_acl = posix_acl_dup(acl); | |
118 | + } | |
119 | + if (value) | |
120 | + kfree(value); | |
121 | + return acl; | |
122 | +} | |
123 | + | |
124 | +int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |
125 | +{ | |
126 | + char *ea_name; | |
127 | + struct jfs_inode_info *ji = JFS_IP(inode); | |
128 | + struct posix_acl **p_acl; | |
129 | + int rc; | |
130 | + int size = 0; | |
131 | + char *value = NULL; | |
132 | + | |
133 | + if (S_ISLNK(inode->i_mode)) | |
134 | + return -ENOTSUP; | |
135 | + | |
136 | + switch(type) { | |
137 | + case ACL_TYPE_ACCESS: | |
138 | + ea_name = XATTR_NAME_ACL_ACCESS; | |
139 | + p_acl = &ji->i_acl; | |
140 | + break; | |
141 | + case ACL_TYPE_DEFAULT: | |
142 | + ea_name = XATTR_NAME_ACL_DEFAULT; | |
143 | + p_acl = &ji->i_default_acl; | |
144 | + if (!S_ISDIR(inode->i_mode)) | |
145 | + return acl ? -EACCES : 0; | |
146 | + break; | |
147 | + default: | |
148 | + return -EINVAL; | |
149 | + } | |
150 | + if (acl) { | |
151 | + size = xattr_acl_size(acl->a_count); | |
152 | + value = kmalloc(size, GFP_KERNEL); | |
153 | + if (!value) | |
154 | + return -ENOMEM; | |
155 | + rc = posix_acl_to_xattr(acl, value, size); | |
156 | + if (rc < 0) | |
157 | + goto out; | |
158 | + } | |
159 | + rc = __jfs_setxattr(inode, ea_name, value, size, 0); | |
160 | +out: | |
161 | + if (value) | |
162 | + kfree(value); | |
163 | + | |
164 | + if (!rc) { | |
165 | + if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED)) | |
166 | + posix_acl_release(*p_acl); | |
167 | + *p_acl = posix_acl_dup(acl); | |
168 | + } | |
169 | + return rc; | |
170 | +} | |
171 | + | |
172 | +/* | |
173 | + * __jfs_permission() | |
174 | + * | |
175 | + * modified vfs_permission to check posix acl | |
176 | + */ | |
177 | +static int __jfs_permission(struct inode * inode, int mask, int have_sem) | |
178 | +{ | |
179 | + umode_t mode = inode->i_mode; | |
180 | + struct jfs_inode_info *ji = JFS_IP(inode); | |
181 | + | |
182 | + if (mask & MAY_WRITE) { | |
183 | + /* | |
184 | + * Nobody gets write access to a read-only fs. | |
185 | + */ | |
186 | + if (IS_RDONLY(inode) && | |
187 | + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) | |
188 | + return -EROFS; | |
189 | + | |
190 | + /* | |
191 | + * Nobody gets write access to an immutable file. | |
192 | + */ | |
193 | + if (IS_IMMUTABLE(inode)) | |
194 | + return -EACCES; | |
195 | + } | |
196 | + | |
197 | + if (current->fsuid == inode->i_uid) { | |
198 | + mode >>= 6; | |
199 | + goto check_mode; | |
200 | + } | |
201 | + /* | |
202 | + * ACL can't contain additional permissions if the ACL_MASK entry | |
203 | + * is zero. | |
204 | + */ | |
205 | + if (!(mode & S_IRWXG)) | |
206 | + goto check_groups; | |
207 | + | |
208 | + if (ji->i_acl == JFS_ACL_NOT_CACHED) { | |
209 | + struct posix_acl *acl; | |
210 | + | |
211 | + if (!have_sem) | |
212 | + down(&inode->i_sem); | |
213 | + acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); | |
214 | + if (!have_sem) | |
215 | + up(&inode->i_sem); | |
216 | + | |
217 | + if (IS_ERR(acl)) | |
218 | + return PTR_ERR(acl); | |
219 | + posix_acl_release(acl); | |
220 | + } | |
221 | + | |
222 | + if (ji->i_acl) { | |
223 | + int rc = posix_acl_permission(inode, ji->i_acl, mask); | |
224 | + if (rc == -EACCES) | |
225 | + goto check_capabilities; | |
226 | + return rc; | |
227 | + } | |
228 | + | |
229 | +check_groups: | |
230 | + if (in_group_p(inode->i_gid)) | |
231 | + mode >>= 3; | |
232 | + | |
233 | +check_mode: | |
234 | + /* | |
235 | + * If the DACs are ok we don't need any capability check. | |
236 | + */ | |
237 | + if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) | |
238 | + return 0; | |
239 | + | |
240 | +check_capabilities: | |
241 | + /* | |
242 | + * Read/write DACs are always overridable. | |
243 | + * Executable DACs are overridable if at least one exec bit is set. | |
244 | + */ | |
245 | + if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO)) | |
246 | + if (capable(CAP_DAC_OVERRIDE)) | |
247 | + return 0; | |
248 | + | |
249 | + /* | |
250 | + * Searching includes executable on directories, else just read. | |
251 | + */ | |
252 | + if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) | |
253 | + if (capable(CAP_DAC_READ_SEARCH)) | |
254 | + return 0; | |
255 | + | |
256 | + return -EACCES; | |
257 | +} | |
258 | +int jfs_permission(struct inode * inode, int mask) | |
259 | +{ | |
260 | + return __jfs_permission(inode, mask, 0); | |
261 | +} | |
262 | +int jfs_permission_have_sem(struct inode * inode, int mask) | |
263 | +{ | |
264 | + return __jfs_permission(inode, mask, 1); | |
265 | +} | |
266 | + | |
267 | +int jfs_init_acl(struct inode *inode, struct inode *dir) | |
268 | +{ | |
269 | + struct posix_acl *acl = NULL; | |
270 | + struct posix_acl *clone; | |
271 | + mode_t mode; | |
272 | + int rc = 0; | |
273 | + | |
274 | + if (S_ISLNK(inode->i_mode)) | |
275 | + return 0; | |
276 | + | |
277 | + acl = jfs_get_acl(dir, ACL_TYPE_DEFAULT); | |
278 | + if (IS_ERR(acl)) | |
279 | + return PTR_ERR(acl); | |
280 | + | |
281 | + if (acl) { | |
282 | + if (S_ISDIR(inode->i_mode)) { | |
283 | + rc = jfs_set_acl(inode, ACL_TYPE_DEFAULT, acl); | |
284 | + if (rc) | |
285 | + goto cleanup; | |
286 | + } | |
287 | + clone = posix_acl_clone(acl, GFP_KERNEL); | |
288 | + if (!clone) { | |
289 | + rc = -ENOMEM; | |
290 | + goto cleanup; | |
291 | + } | |
292 | + mode = inode->i_mode; | |
293 | + rc = posix_acl_create_masq(clone, &mode); | |
294 | + if (rc >= 0) { | |
295 | + inode->i_mode = mode; | |
296 | + if (rc > 0) | |
297 | + rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone); | |
298 | + } | |
299 | + posix_acl_release(clone); | |
300 | +cleanup: | |
301 | + posix_acl_release(acl); | |
302 | + } else | |
303 | + inode->i_mode &= ~current->fs->umask; | |
304 | + | |
305 | + return rc; | |
306 | +} | |
307 | + | |
308 | +int jfs_acl_chmod(struct inode *inode) | |
309 | +{ | |
310 | + struct posix_acl *acl, *clone; | |
311 | + int rc; | |
312 | + | |
313 | + if (S_ISLNK(inode->i_mode)) | |
314 | + return -ENOTSUP; | |
315 | + | |
316 | + acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); | |
317 | + if (IS_ERR(acl) || !acl) | |
318 | + return PTR_ERR(acl); | |
319 | + | |
320 | + clone = posix_acl_clone(acl, GFP_KERNEL); | |
321 | + posix_acl_release(acl); | |
322 | + if (!clone) | |
323 | + return -ENOMEM; | |
324 | + | |
325 | + rc = posix_acl_chmod_masq(clone, inode->i_mode); | |
326 | + if (!rc) | |
327 | + rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone); | |
328 | + | |
329 | + posix_acl_release(clone); | |
330 | + return rc; | |
331 | +} | |
332 | + | |
333 | +int jfs_setattr(struct dentry *dentry, struct iattr *iattr) | |
334 | +{ | |
335 | + struct inode *inode = dentry->d_inode; | |
336 | + int rc; | |
337 | + | |
338 | + rc = inode_change_ok(inode, iattr); | |
339 | + if (rc) | |
340 | + return rc; | |
341 | + | |
342 | + inode_setattr(inode, iattr); | |
343 | + | |
344 | + if (iattr->ia_valid & ATTR_MODE) { | |
345 | + /* | |
346 | + * Mode change may affect acl. i_sem already held by | |
347 | + * truncate (ia_valid & ATTR_SIZE) | |
348 | + */ | |
349 | + if (!(iattr->ia_valid & ATTR_SIZE)) | |
350 | + down(&inode->i_sem); | |
351 | + rc = jfs_acl_chmod(inode); | |
352 | + if (!(iattr->ia_valid & ATTR_SIZE)) | |
353 | + up(&inode->i_sem); | |
354 | + } | |
355 | + return rc; | |
356 | +} | |
357 | diff -Nur linux-2.4.20-xattr/fs/jfs/file.c linux-2.4.20-acl/fs/jfs/file.c | |
358 | --- linux-2.4.20-xattr/fs/jfs/file.c 2003-02-03 14:37:52.000000000 -0600 | |
359 | +++ linux-2.4.20-acl/fs/jfs/file.c 2003-02-03 14:38:41.000000000 -0600 | |
360 | @@ -23,6 +23,7 @@ | |
361 | #include "jfs_dmap.h" | |
362 | #include "jfs_txnmgr.h" | |
363 | #include "jfs_xattr.h" | |
364 | +#include "jfs_acl.h" | |
365 | #include "jfs_debug.h" | |
366 | ||
367 | ||
368 | @@ -96,6 +97,12 @@ | |
369 | .getxattr = jfs_getxattr, | |
370 | .listxattr = jfs_listxattr, | |
371 | .removexattr = jfs_removexattr, | |
372 | +#ifdef CONFIG_JFS_POSIX_ACL | |
373 | + .setattr = jfs_setattr, | |
374 | + .permission = jfs_permission, | |
375 | + .get_posix_acl = jfs_get_acl, | |
376 | + .set_posix_acl = jfs_set_acl, | |
377 | +#endif | |
378 | }; | |
379 | ||
380 | struct file_operations jfs_file_operations = { | |
381 | @@ -113,5 +120,11 @@ | |
382 | .getxattr = jfs_getxattr, | |
383 | .listxattr = jfs_listxattr, | |
384 | .removexattr = jfs_removexattr, | |
385 | +#ifdef CONFIG_JFS_POSIX_ACL | |
386 | + .setattr = jfs_setattr, | |
387 | + .permission = jfs_permission, | |
388 | + .get_posix_acl = jfs_get_acl, | |
389 | + .set_posix_acl = jfs_set_acl, | |
390 | +#endif | |
391 | }; | |
392 | ||
393 | diff -Nur linux-2.4.20-xattr/fs/jfs/inode.c linux-2.4.20-acl/fs/jfs/inode.c | |
394 | --- linux-2.4.20-xattr/fs/jfs/inode.c 2003-02-03 14:37:52.000000000 -0600 | |
395 | +++ linux-2.4.20-acl/fs/jfs/inode.c 2003-02-03 14:38:41.000000000 -0600 | |
396 | @@ -24,6 +24,7 @@ | |
397 | #include "jfs_dmap.h" | |
398 | #include "jfs_imap.h" | |
399 | #include "jfs_extent.h" | |
400 | +#include "jfs_acl.h" | |
401 | #include "jfs_unicode.h" | |
402 | #include "jfs_debug.h" | |
403 | ||
404 | @@ -57,6 +58,17 @@ | |
405 | ||
406 | ASSERT(list_empty(&ji->anon_inode_list)); | |
407 | ||
408 | +#ifdef CONFIG_JFS_POSIX_ACL | |
409 | + if (ji->i_acl && (ji->i_acl != JFS_ACL_NOT_CACHED)) { | |
410 | + posix_acl_release(ji->i_acl); | |
411 | + ji->i_acl = JFS_ACL_NOT_CACHED; | |
412 | + } | |
413 | + if (ji->i_default_acl && (ji->i_default_acl != JFS_ACL_NOT_CACHED)) { | |
414 | + posix_acl_release(ji->i_default_acl); | |
415 | + ji->i_default_acl = JFS_ACL_NOT_CACHED; | |
416 | + } | |
417 | +#endif | |
418 | + | |
419 | if (ji->atlhead) { | |
420 | jERROR(1, ("jfs_clear_inode: inode %p has anonymous tlocks\n", | |
421 | inode)); | |
422 | diff -Nur linux-2.4.20-xattr/fs/jfs/jfs_acl.h linux-2.4.20-acl/fs/jfs/jfs_acl.h | |
423 | --- linux-2.4.20-xattr/fs/jfs/jfs_acl.h 1969-12-31 18:00:00.000000000 -0600 | |
424 | +++ linux-2.4.20-acl/fs/jfs/jfs_acl.h 2003-02-03 14:38:41.000000000 -0600 | |
425 | @@ -0,0 +1,34 @@ | |
426 | +/* | |
427 | + * Copyright (c) International Business Machines Corp., 2002 | |
428 | + * | |
429 | + * This program is free software; you can redistribute it and/or modify | |
430 | + * it under the terms of the GNU General Public License as published by | |
431 | + * the Free Software Foundation; either version 2 of the License, or | |
432 | + * (at your option) any later version. | |
433 | + * | |
434 | + * This program is distributed in the hope that it will be useful, | |
435 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
436 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | |
437 | + * the GNU General Public License for more details. | |
438 | + * | |
439 | + * You should have received a copy of the GNU General Public License | |
440 | + * along with this program; if not, write to the Free Software | |
441 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
442 | + */ | |
443 | +#ifndef _H_JFS_ACL | |
444 | +#define _H_JFS_ACL | |
445 | + | |
446 | +#ifdef CONFIG_JFS_POSIX_ACL | |
447 | + | |
448 | +#include <linux/xattr_acl.h> | |
449 | + | |
450 | +struct posix_acl *jfs_get_acl(struct inode *, int); | |
451 | +int jfs_set_acl(struct inode *, int, struct posix_acl *); | |
452 | +int jfs_permission_have_sem(struct inode *, int); | |
453 | +int jfs_permission(struct inode *, int); | |
454 | +int jfs_init_acl(struct inode *, struct inode *); | |
455 | +int jfs_setattr(struct dentry *, struct iattr *); | |
456 | + | |
457 | +#endif /* CONFIG_JFS_POSIX_ACL */ | |
458 | + | |
459 | +#endif /* _H_JFS_ACL */ | |
460 | diff -Nur linux-2.4.20-xattr/fs/jfs/jfs_imap.c linux-2.4.20-acl/fs/jfs/jfs_imap.c | |
461 | --- linux-2.4.20-xattr/fs/jfs/jfs_imap.c 2003-02-03 14:37:52.000000000 -0600 | |
462 | +++ linux-2.4.20-acl/fs/jfs/jfs_imap.c 2003-02-03 14:38:41.000000000 -0600 | |
463 | @@ -821,7 +821,7 @@ | |
464 | lv = & dilinelock->lv[dilinelock->index]; | |
465 | lv->offset = (dioffset + 3 * 128) >> L2INODESLOTSIZE; | |
466 | lv->length = 1; | |
467 | - memcpy(&dp->di_inlineea, &jfs_ip->i_inline_ea, INODESLOTSIZE); | |
468 | + memcpy(&dp->di_inlineea, jfs_ip->i_inline_ea, INODESLOTSIZE); | |
469 | dilinelock->index++; | |
470 | ||
471 | clear_cflag(COMMIT_Inlineea, ip); | |
472 | diff -Nur linux-2.4.20-xattr/fs/jfs/jfs_incore.h linux-2.4.20-acl/fs/jfs/jfs_incore.h | |
473 | --- linux-2.4.20-xattr/fs/jfs/jfs_incore.h 2003-02-03 14:37:52.000000000 -0600 | |
474 | +++ linux-2.4.20-acl/fs/jfs/jfs_incore.h 2003-02-03 14:38:41.000000000 -0600 | |
475 | @@ -69,6 +69,10 @@ | |
476 | */ | |
477 | struct semaphore commit_sem; | |
478 | lid_t xtlid; /* lid of xtree lock on directory */ | |
479 | +#ifdef CONFIG_JFS_POSIX_ACL | |
480 | + struct posix_acl *i_acl; | |
481 | + struct posix_acl *i_default_acl; | |
482 | +#endif | |
483 | union { | |
484 | struct { | |
485 | xtpage_t _xtroot; /* 288: xtree root */ | |
486 | @@ -96,6 +100,7 @@ | |
487 | #define i_inline u.link._inline | |
488 | #define i_inline_ea u.link._inline_ea | |
489 | ||
490 | +#define JFS_ACL_NOT_CACHED ((void *)-1) | |
491 | ||
492 | #define IREAD_LOCK(ip) down_read(&JFS_IP(ip)->rdwrlock) | |
493 | #define IREAD_UNLOCK(ip) up_read(&JFS_IP(ip)->rdwrlock) | |
494 | diff -Nur linux-2.4.20-xattr/fs/jfs/namei.c linux-2.4.20-acl/fs/jfs/namei.c | |
495 | --- linux-2.4.20-xattr/fs/jfs/namei.c 2003-02-03 14:37:52.000000000 -0600 | |
496 | +++ linux-2.4.20-acl/fs/jfs/namei.c 2003-02-03 14:39:12.000000000 -0600 | |
497 | @@ -25,6 +25,7 @@ | |
498 | #include "jfs_unicode.h" | |
499 | #include "jfs_metapage.h" | |
500 | #include "jfs_xattr.h" | |
501 | +#include "jfs_acl.h" | |
502 | #include "jfs_debug.h" | |
503 | ||
504 | extern struct inode_operations jfs_file_inode_operations; | |
505 | @@ -35,6 +36,7 @@ | |
506 | ||
507 | extern int jfs_fsync(struct file *, struct dentry *, int); | |
508 | extern void jfs_truncate_nolock(struct inode *, loff_t); | |
509 | +extern int jfs_init_acl(struct inode *, struct inode *); | |
510 | ||
511 | /* | |
512 | * forward references | |
513 | @@ -150,6 +152,11 @@ | |
514 | out2: | |
515 | free_UCSname(&dname); | |
516 | ||
517 | +#ifdef CONFIG_JFS_POSIX_ACL | |
518 | + if (rc == 0) | |
519 | + jfs_init_acl(ip, dip); | |
520 | +#endif | |
521 | + | |
522 | out1: | |
523 | ||
524 | jFYI(1, ("jfs_create: rc:%d\n", -rc)); | |
525 | @@ -275,6 +282,11 @@ | |
526 | out2: | |
527 | free_UCSname(&dname); | |
528 | ||
529 | +#ifdef CONFIG_JFS_POSIX_ACL | |
530 | + if (rc == 0) | |
531 | + jfs_init_acl(ip, dip); | |
532 | +#endif | |
533 | + | |
534 | out1: | |
535 | ||
536 | jFYI(1, ("jfs_mkdir: rc:%d\n", -rc)); | |
537 | @@ -1019,6 +1031,11 @@ | |
538 | out2: | |
539 | free_UCSname(&dname); | |
540 | ||
541 | +#ifdef CONFIG_JFS_POSIX_ACL | |
542 | + if (rc == 0) | |
543 | + jfs_init_acl(ip, dip); | |
544 | +#endif | |
545 | + | |
546 | out1: | |
547 | jFYI(1, ("jfs_symlink: rc:%d\n", -rc)); | |
548 | return -rc; | |
549 | @@ -1359,6 +1376,11 @@ | |
550 | out1: | |
551 | free_UCSname(&dname); | |
552 | ||
553 | +#ifdef CONFIG_JFS_POSIX_ACL | |
554 | + if (rc == 0) | |
555 | + jfs_init_acl(ip, dir); | |
556 | +#endif | |
557 | + | |
558 | out: | |
559 | jFYI(1, ("jfs_mknod: returning %d\n", rc)); | |
560 | return -rc; | |
561 | @@ -1424,6 +1446,12 @@ | |
562 | .getxattr = jfs_getxattr, | |
563 | .listxattr = jfs_listxattr, | |
564 | .removexattr = jfs_removexattr, | |
565 | +#ifdef CONFIG_JFS_POSIX_ACL | |
566 | + .setattr = jfs_setattr, | |
567 | + .permission = jfs_permission, | |
568 | + .get_posix_acl = jfs_get_acl, | |
569 | + .set_posix_acl = jfs_set_acl, | |
570 | +#endif | |
571 | }; | |
572 | ||
573 | struct file_operations jfs_dir_operations = { | |
574 | diff -Nur linux-2.4.20-xattr/fs/jfs/super.c linux-2.4.20-acl/fs/jfs/super.c | |
575 | --- linux-2.4.20-xattr/fs/jfs/super.c 2003-02-03 14:36:39.000000000 -0600 | |
576 | +++ linux-2.4.20-acl/fs/jfs/super.c 2003-02-03 14:38:41.000000000 -0600 | |
577 | @@ -442,6 +442,10 @@ | |
578 | init_MUTEX(&jfs_ip->commit_sem); | |
579 | jfs_ip->atlhead = 0; | |
580 | jfs_ip->active_ag = -1; | |
581 | +#ifdef CONFIG_JFS_POSIX_ACL | |
582 | + jfs_ip->i_acl = JFS_ACL_NOT_CACHED; | |
583 | + jfs_ip->i_default_acl = JFS_ACL_NOT_CACHED; | |
584 | +#endif | |
585 | } | |
586 | } | |
587 | ||
588 | diff -Nur linux-2.4.20-xattr/fs/jfs/xattr.c linux-2.4.20-acl/fs/jfs/xattr.c | |
589 | --- linux-2.4.20-xattr/fs/jfs/xattr.c 2003-02-03 14:37:52.000000000 -0600 | |
590 | +++ linux-2.4.20-acl/fs/jfs/xattr.c 2003-02-03 14:39:12.000000000 -0600 | |
591 | @@ -26,6 +26,7 @@ | |
592 | #include "jfs_extent.h" | |
593 | #include "jfs_metapage.h" | |
594 | #include "jfs_xattr.h" | |
595 | +#include "jfs_acl.h" | |
596 | ||
597 | /* | |
598 | * jfs_xattr.c: extended attribute service | |
599 | @@ -201,7 +202,6 @@ | |
600 | ji->mode2 |= INLINEEA; | |
601 | } | |
602 | ||
603 | - mark_inode_dirty(ip); | |
604 | return 0; | |
605 | } | |
606 | ||
607 | @@ -640,6 +640,71 @@ | |
608 | return rc; | |
609 | } | |
610 | ||
611 | +/* | |
612 | + * can_set_system_xattr | |
613 | + * | |
614 | + * This code is specific to the system.* namespace. It contains policy | |
615 | + * which doesn't belong in the main xattr codepath. | |
616 | + */ | |
617 | +static int can_set_system_xattr(struct inode *inode, const char *name, | |
618 | + const void *value, size_t value_len) | |
619 | +{ | |
620 | +#ifdef CONFIG_JFS_POSIX_ACL | |
621 | + struct posix_acl *acl; | |
622 | + int rc; | |
623 | + | |
624 | + if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | |
625 | + return -EPERM; | |
626 | + | |
627 | + /* | |
628 | + * XATTR_NAME_ACL_ACCESS is tied to i_mode | |
629 | + */ | |
630 | + if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) { | |
631 | + acl = posix_acl_from_xattr(value, value_len); | |
632 | + if (acl < 0) { | |
633 | + printk(KERN_ERR "posix_acl_from_xattr returned %d\n", | |
634 | + rc); | |
635 | + return rc; | |
636 | + } | |
637 | + if (acl > 0) { | |
638 | + mode_t mode = inode->i_mode; | |
639 | + rc = posix_acl_equiv_mode(acl, &mode); | |
640 | + posix_acl_release(acl); | |
641 | + if (rc < 0) { | |
642 | + printk(KERN_ERR | |
643 | + "posix_acl_equiv_mode returned %d\n", | |
644 | + rc); | |
645 | + return rc; | |
646 | + } | |
647 | + inode->i_mode = mode; | |
648 | + mark_inode_dirty(inode); | |
649 | + if (rc == 0) | |
650 | + value = NULL; | |
651 | + } | |
652 | + /* | |
653 | + * We're changing the ACL. Get rid of the cached one | |
654 | + */ | |
655 | + acl =JFS_IP(inode)->i_acl; | |
656 | + if (acl && (acl != JFS_ACL_NOT_CACHED)) | |
657 | + posix_acl_release(acl); | |
658 | + JFS_IP(inode)->i_acl = JFS_ACL_NOT_CACHED; | |
659 | + } else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) { | |
660 | + /* | |
661 | + * We're changing the default ACL. Get rid of the cached one | |
662 | + */ | |
663 | + acl =JFS_IP(inode)->i_default_acl; | |
664 | + if (acl && (acl != JFS_ACL_NOT_CACHED)) | |
665 | + posix_acl_release(acl); | |
666 | + JFS_IP(inode)->i_default_acl = JFS_ACL_NOT_CACHED; | |
667 | + } else | |
668 | + /* Invalid xattr name */ | |
669 | + return -EINVAL; | |
670 | + return 0; | |
671 | +#else /* CONFIG_JFS_POSIX_ACL */ | |
672 | + return -ENOTSUP; | |
673 | +#endif /* CONFIG_JFS_POSIX_ACL */ | |
674 | +} | |
675 | + | |
676 | static int can_set_xattr(struct inode *inode, const char *name, | |
677 | const void *value, size_t value_len) | |
678 | { | |
679 | @@ -649,6 +714,12 @@ | |
680 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode) || S_ISLNK(inode->i_mode)) | |
681 | return -EPERM; | |
682 | ||
683 | + if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0) | |
684 | + /* | |
685 | + * "system.*" | |
686 | + */ | |
687 | + return can_set_system_xattr(inode, name, value, value_len); | |
688 | + | |
689 | if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) && | |
690 | (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0)) | |
691 | return -ENOTSUP; | |
692 | @@ -657,7 +728,11 @@ | |
693 | (!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX)) | |
694 | return -EPERM; | |
695 | ||
696 | +#ifdef CONFIG_JFS_POSIX_ACL | |
697 | + return jfs_permission_have_sem(inode, MAY_WRITE); | |
698 | +#else | |
699 | return permission(inode, MAY_WRITE); | |
700 | +#endif | |
701 | } | |
702 | ||
703 | int __jfs_setxattr(struct inode *inode, const char *name, const void *value, | |
704 | @@ -810,9 +885,16 @@ | |
705 | return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags); | |
706 | } | |
707 | ||
708 | -static inline int can_get_xattr(struct inode *inode, const char *name) | |
709 | +static int can_get_xattr(struct inode *inode, const char *name) | |
710 | { | |
711 | +#ifdef CONFIG_JFS_POSIX_ACL | |
712 | + if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0) | |
713 | + return 0; | |
714 | + else | |
715 | + return jfs_permission_have_sem(inode, MAY_READ); | |
716 | +#else | |
717 | return permission(inode, MAY_READ); | |
718 | +#endif | |
719 | } | |
720 | ||
721 | ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, |