aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/dir.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2007-04-26 18:57:07 -0400
committerDavid S. Miller <davem@davemloft.net>2007-04-26 18:57:07 -0400
commit00d3b7a4533e367b0dc2812a706db8f9f071c27f (patch)
treef0b1ae0266267cb2c54cb11aa61ad0758ce9c0f5 /fs/afs/dir.c
parent436058a49e0fb91c74454dbee9cfee6fb53b4336 (diff)
[AFS]: Add security support.
Add security support to the AFS filesystem. Kerberos IV tickets are added as RxRPC keys are added to the session keyring with the klog program. open() and other VFS operations then find this ticket with request_key() and either use it immediately (eg: mkdir, unlink) or attach it to a file descriptor (open). Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs/afs/dir.c')
-rw-r--r--fs/afs/dir.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index d7697f6f3b7f..87368417e4d3 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -15,6 +15,7 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/fs.h> 16#include <linux/fs.h>
17#include <linux/pagemap.h> 17#include <linux/pagemap.h>
18#include <linux/ctype.h>
18#include "internal.h" 19#include "internal.h"
19 20
20static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, 21static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
@@ -28,11 +29,13 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
28 29
29const struct file_operations afs_dir_file_operations = { 30const struct file_operations afs_dir_file_operations = {
30 .open = afs_dir_open, 31 .open = afs_dir_open,
32 .release = afs_release,
31 .readdir = afs_dir_readdir, 33 .readdir = afs_dir_readdir,
32}; 34};
33 35
34const struct inode_operations afs_dir_inode_operations = { 36const struct inode_operations afs_dir_inode_operations = {
35 .lookup = afs_dir_lookup, 37 .lookup = afs_dir_lookup,
38 .permission = afs_permission,
36 .getattr = afs_inode_getattr, 39 .getattr = afs_inode_getattr,
37#if 0 /* TODO */ 40#if 0 /* TODO */
38 .create = afs_dir_create, 41 .create = afs_dir_create,
@@ -169,13 +172,17 @@ static inline void afs_dir_put_page(struct page *page)
169/* 172/*
170 * get a page into the pagecache 173 * get a page into the pagecache
171 */ 174 */
172static struct page *afs_dir_get_page(struct inode *dir, unsigned long index) 175static struct page *afs_dir_get_page(struct inode *dir, unsigned long index,
176 struct key *key)
173{ 177{
174 struct page *page; 178 struct page *page;
179 struct file file = {
180 .private_data = key,
181 };
175 182
176 _enter("{%lu},%lu", dir->i_ino, index); 183 _enter("{%lu},%lu", dir->i_ino, index);
177 184
178 page = read_mapping_page(dir->i_mapping, index, NULL); 185 page = read_mapping_page(dir->i_mapping, index, &file);
179 if (!IS_ERR(page)) { 186 if (!IS_ERR(page)) {
180 wait_on_page_locked(page); 187 wait_on_page_locked(page);
181 kmap(page); 188 kmap(page);
@@ -207,8 +214,7 @@ static int afs_dir_open(struct inode *inode, struct file *file)
207 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags)) 214 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
208 return -ENOENT; 215 return -ENOENT;
209 216
210 _leave(" = 0"); 217 return afs_open(inode, file);
211 return 0;
212} 218}
213 219
214/* 220/*
@@ -311,7 +317,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
311 * iterate through the data blob that lists the contents of an AFS directory 317 * iterate through the data blob that lists the contents of an AFS directory
312 */ 318 */
313static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, 319static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
314 filldir_t filldir) 320 filldir_t filldir, struct key *key)
315{ 321{
316 union afs_dir_block *dblock; 322 union afs_dir_block *dblock;
317 struct afs_dir_page *dbuf; 323 struct afs_dir_page *dbuf;
@@ -336,7 +342,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
336 blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1); 342 blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1);
337 343
338 /* fetch the appropriate page from the directory */ 344 /* fetch the appropriate page from the directory */
339 page = afs_dir_get_page(dir, blkoff / PAGE_SIZE); 345 page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key);
340 if (IS_ERR(page)) { 346 if (IS_ERR(page)) {
341 ret = PTR_ERR(page); 347 ret = PTR_ERR(page);
342 break; 348 break;
@@ -381,9 +387,11 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir)
381 _enter("{%Ld,{%lu}}", 387 _enter("{%Ld,{%lu}}",
382 file->f_pos, file->f_path.dentry->d_inode->i_ino); 388 file->f_pos, file->f_path.dentry->d_inode->i_ino);
383 389
390 ASSERT(file->private_data != NULL);
391
384 fpos = file->f_pos; 392 fpos = file->f_pos;
385 ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, 393 ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos,
386 cookie, filldir); 394 cookie, filldir, file->private_data);
387 file->f_pos = fpos; 395 file->f_pos = fpos;
388 396
389 _leave(" = %d", ret); 397 _leave(" = %d", ret);
@@ -424,7 +432,7 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
424 * do a lookup in a directory 432 * do a lookup in a directory
425 */ 433 */
426static int afs_do_lookup(struct inode *dir, struct dentry *dentry, 434static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
427 struct afs_fid *fid) 435 struct afs_fid *fid, struct key *key)
428{ 436{
429 struct afs_dir_lookup_cookie cookie; 437 struct afs_dir_lookup_cookie cookie;
430 struct afs_super_info *as; 438 struct afs_super_info *as;
@@ -442,7 +450,8 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
442 cookie.found = 0; 450 cookie.found = 0;
443 451
444 fpos = 0; 452 fpos = 0;
445 ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir); 453 ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir,
454 key);
446 if (ret < 0) { 455 if (ret < 0) {
447 _leave(" = %d [iter]", ret); 456 _leave(" = %d [iter]", ret);
448 return ret; 457 return ret;
@@ -468,6 +477,7 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
468 struct afs_vnode *vnode; 477 struct afs_vnode *vnode;
469 struct afs_fid fid; 478 struct afs_fid fid;
470 struct inode *inode; 479 struct inode *inode;
480 struct key *key;
471 int ret; 481 int ret;
472 482
473 _enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name); 483 _enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name);
@@ -483,14 +493,22 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
483 return ERR_PTR(-ESTALE); 493 return ERR_PTR(-ESTALE);
484 } 494 }
485 495
486 ret = afs_do_lookup(dir, dentry, &fid); 496 key = afs_request_key(vnode->volume->cell);
497 if (IS_ERR(key)) {
498 _leave(" = %ld [key]", PTR_ERR(key));
499 return ERR_PTR(PTR_ERR(key));
500 }
501
502 ret = afs_do_lookup(dir, dentry, &fid, key);
487 if (ret < 0) { 503 if (ret < 0) {
504 key_put(key);
488 _leave(" = %d [do]", ret); 505 _leave(" = %d [do]", ret);
489 return ERR_PTR(ret); 506 return ERR_PTR(ret);
490 } 507 }
491 508
492 /* instantiate the dentry */ 509 /* instantiate the dentry */
493 inode = afs_iget(dir->i_sb, &fid); 510 inode = afs_iget(dir->i_sb, key, &fid);
511 key_put(key);
494 if (IS_ERR(inode)) { 512 if (IS_ERR(inode)) {
495 _leave(" = %ld", PTR_ERR(inode)); 513 _leave(" = %ld", PTR_ERR(inode));
496 return ERR_PTR(PTR_ERR(inode)); 514 return ERR_PTR(PTR_ERR(inode));
@@ -559,6 +577,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
559 struct afs_fid fid; 577 struct afs_fid fid;
560 struct dentry *parent; 578 struct dentry *parent;
561 struct inode *inode, *dir; 579 struct inode *inode, *dir;
580 struct key *key;
562 int ret; 581 int ret;
563 582
564 vnode = AFS_FS_I(dentry->d_inode); 583 vnode = AFS_FS_I(dentry->d_inode);
@@ -566,6 +585,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
566 _enter("{sb=%p n=%s fl=%lx},", 585 _enter("{sb=%p n=%s fl=%lx},",
567 dentry->d_sb, dentry->d_name.name, vnode->flags); 586 dentry->d_sb, dentry->d_name.name, vnode->flags);
568 587
588 key = afs_request_key(vnode->volume->cell);
589 if (IS_ERR(key))
590 key = NULL;
591
569 /* lock down the parent dentry so we can peer at it */ 592 /* lock down the parent dentry so we can peer at it */
570 parent = dget_parent(dentry); 593 parent = dget_parent(dentry);
571 594
@@ -595,7 +618,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
595 _debug("dir modified"); 618 _debug("dir modified");
596 619
597 /* search the directory for this vnode */ 620 /* search the directory for this vnode */
598 ret = afs_do_lookup(dir, dentry, &fid); 621 ret = afs_do_lookup(dir, dentry, &fid, key);
599 if (ret == -ENOENT) { 622 if (ret == -ENOENT) {
600 _debug("%s: dirent not found", dentry->d_name.name); 623 _debug("%s: dirent not found", dentry->d_name.name);
601 goto not_found; 624 goto not_found;
@@ -637,7 +660,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
637 test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { 660 test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) {
638 _debug("%s: changed", dentry->d_name.name); 661 _debug("%s: changed", dentry->d_name.name);
639 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags); 662 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
640 if (afs_vnode_fetch_status(vnode) < 0) { 663 if (afs_vnode_fetch_status(vnode, NULL, key) < 0) {
641 mutex_unlock(&vnode->cb_broken_lock); 664 mutex_unlock(&vnode->cb_broken_lock);
642 goto out_bad; 665 goto out_bad;
643 } 666 }
@@ -667,6 +690,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
667 690
668out_valid: 691out_valid:
669 dput(parent); 692 dput(parent);
693 key_put(key);
670 _leave(" = 1 [valid]"); 694 _leave(" = 1 [valid]");
671 return 1; 695 return 1;
672 696
@@ -688,6 +712,7 @@ out_bad:
688 shrink_dcache_parent(dentry); 712 shrink_dcache_parent(dentry);
689 d_drop(dentry); 713 d_drop(dentry);
690 dput(parent); 714 dput(parent);
715 key_put(key);
691 716
692 _leave(" = 0 [bad]"); 717 _leave(" = 0 [bad]");
693 return 0; 718 return 0;