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