aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/afs/Makefile1
-rw-r--r--fs/afs/afs.h27
-rw-r--r--fs/afs/callback.c5
-rw-r--r--fs/afs/cell.c98
-rw-r--r--fs/afs/cmservice.c3
-rw-r--r--fs/afs/dir.c51
-rw-r--r--fs/afs/file.c60
-rw-r--r--fs/afs/fsclient.c9
-rw-r--r--fs/afs/inode.c21
-rw-r--r--fs/afs/internal.h106
-rw-r--r--fs/afs/mntpt.c12
-rw-r--r--fs/afs/rxrpc.c137
-rw-r--r--fs/afs/security.c345
-rw-r--r--fs/afs/super.c142
-rw-r--r--fs/afs/vlclient.c6
-rw-r--r--fs/afs/vlocation.c26
-rw-r--r--fs/afs/vnode.c25
-rw-r--r--fs/afs/volume.c109
18 files changed, 945 insertions, 238 deletions
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 66bdc219ccde..cca198b2caed 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -15,6 +15,7 @@ kafs-objs := \
15 mntpt.o \ 15 mntpt.o \
16 proc.o \ 16 proc.o \
17 rxrpc.o \ 17 rxrpc.o \
18 security.o \
18 server.o \ 19 server.o \
19 super.o \ 20 super.o \
20 vlclient.o \ 21 vlclient.o \
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index b9d2d2ceaf43..d959092aaf4b 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -14,6 +14,9 @@
14 14
15#include <linux/in.h> 15#include <linux/in.h>
16 16
17#define AFS_MAXCELLNAME 64 /* maximum length of a cell name */
18#define AFS_MAXVOLNAME 64 /* maximum length of a volume name */
19
17typedef unsigned afs_volid_t; 20typedef unsigned afs_volid_t;
18typedef unsigned afs_vnodeid_t; 21typedef unsigned afs_vnodeid_t;
19typedef unsigned long long afs_dataversion_t; 22typedef unsigned long long afs_dataversion_t;
@@ -75,6 +78,26 @@ struct afs_volume_info {
75}; 78};
76 79
77/* 80/*
81 * AFS security ACE access mask
82 */
83typedef u32 afs_access_t;
84#define AFS_ACE_READ 0x00000001U /* - permission to read a file/dir */
85#define AFS_ACE_WRITE 0x00000002U /* - permission to write/chmod a file */
86#define AFS_ACE_INSERT 0x00000004U /* - permission to create dirent in a dir */
87#define AFS_ACE_LOOKUP 0x00000008U /* - permission to lookup a file/dir in a dir */
88#define AFS_ACE_DELETE 0x00000010U /* - permission to delete a dirent from a dir */
89#define AFS_ACE_LOCK 0x00000020U /* - permission to lock a file */
90#define AFS_ACE_ADMINISTER 0x00000040U /* - permission to change ACL */
91#define AFS_ACE_USER_A 0x01000000U /* - 'A' user-defined permission */
92#define AFS_ACE_USER_B 0x02000000U /* - 'B' user-defined permission */
93#define AFS_ACE_USER_C 0x04000000U /* - 'C' user-defined permission */
94#define AFS_ACE_USER_D 0x08000000U /* - 'D' user-defined permission */
95#define AFS_ACE_USER_E 0x10000000U /* - 'E' user-defined permission */
96#define AFS_ACE_USER_F 0x20000000U /* - 'F' user-defined permission */
97#define AFS_ACE_USER_G 0x40000000U /* - 'G' user-defined permission */
98#define AFS_ACE_USER_H 0x80000000U /* - 'H' user-defined permission */
99
100/*
78 * AFS file status information 101 * AFS file status information
79 */ 102 */
80struct afs_file_status { 103struct afs_file_status {
@@ -87,8 +110,8 @@ struct afs_file_status {
87 afs_dataversion_t data_version; /* current data version */ 110 afs_dataversion_t data_version; /* current data version */
88 unsigned author; /* author ID */ 111 unsigned author; /* author ID */
89 unsigned owner; /* owner ID */ 112 unsigned owner; /* owner ID */
90 unsigned caller_access; /* access rights for authenticated caller */ 113 afs_access_t caller_access; /* access rights for authenticated caller */
91 unsigned anon_access; /* access rights for unauthenticated caller */ 114 afs_access_t anon_access; /* access rights for unauthenticated caller */
92 umode_t mode; /* UNIX mode */ 115 umode_t mode; /* UNIX mode */
93 struct afs_fid parent; /* parent file ID */ 116 struct afs_fid parent; /* parent file ID */
94 time_t mtime_client; /* last time client changed data */ 117 time_t mtime_client; /* last time client changed data */
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index 611215547142..e674bebbb8b1 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -72,7 +72,10 @@ void afs_broken_callback_work(struct work_struct *work)
72 return; /* someone else is dealing with it */ 72 return; /* someone else is dealing with it */
73 73
74 if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { 74 if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) {
75 if (afs_vnode_fetch_status(vnode) < 0) 75 if (S_ISDIR(vnode->vfs_inode.i_mode))
76 afs_clear_permits(vnode);
77
78 if (afs_vnode_fetch_status(vnode, NULL, NULL) < 0)
76 goto out; 79 goto out;
77 80
78 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) 81 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index 733c60246ab0..9b1311a1df51 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -11,6 +11,9 @@
11 11
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/key.h>
15#include <linux/ctype.h>
16#include <keys/rxrpc-type.h>
14#include "internal.h" 17#include "internal.h"
15 18
16DECLARE_RWSEM(afs_proc_cells_sem); 19DECLARE_RWSEM(afs_proc_cells_sem);
@@ -23,45 +26,43 @@ static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq);
23static struct afs_cell *afs_cell_root; 26static struct afs_cell *afs_cell_root;
24 27
25/* 28/*
26 * create a cell record 29 * allocate a cell record and fill in its name, VL server address list and
27 * - "name" is the name of the cell 30 * allocate an anonymous key
28 * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format
29 */ 31 */
30struct afs_cell *afs_cell_create(const char *name, char *vllist) 32static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
31{ 33{
32 struct afs_cell *cell; 34 struct afs_cell *cell;
33 char *next; 35 size_t namelen;
36 char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
34 int ret; 37 int ret;
35 38
36 _enter("%s,%s", name, vllist); 39 _enter("%s,%s", name, vllist);
37 40
38 BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ 41 BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */
39 42
43 namelen = strlen(name);
44 if (namelen > AFS_MAXCELLNAME)
45 return ERR_PTR(-ENAMETOOLONG);
46
40 /* allocate and initialise a cell record */ 47 /* allocate and initialise a cell record */
41 cell = kmalloc(sizeof(struct afs_cell) + strlen(name) + 1, GFP_KERNEL); 48 cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL);
42 if (!cell) { 49 if (!cell) {
43 _leave(" = -ENOMEM"); 50 _leave(" = -ENOMEM");
44 return ERR_PTR(-ENOMEM); 51 return ERR_PTR(-ENOMEM);
45 } 52 }
46 53
47 down_write(&afs_cells_sem); 54 memcpy(cell->name, name, namelen);
55 cell->name[namelen] = 0;
48 56
49 memset(cell, 0, sizeof(struct afs_cell));
50 atomic_set(&cell->usage, 1); 57 atomic_set(&cell->usage, 1);
51
52 INIT_LIST_HEAD(&cell->link); 58 INIT_LIST_HEAD(&cell->link);
53
54 rwlock_init(&cell->servers_lock); 59 rwlock_init(&cell->servers_lock);
55 INIT_LIST_HEAD(&cell->servers); 60 INIT_LIST_HEAD(&cell->servers);
56
57 init_rwsem(&cell->vl_sem); 61 init_rwsem(&cell->vl_sem);
58 INIT_LIST_HEAD(&cell->vl_list); 62 INIT_LIST_HEAD(&cell->vl_list);
59 spin_lock_init(&cell->vl_lock); 63 spin_lock_init(&cell->vl_lock);
60 64
61 strcpy(cell->name, name);
62
63 /* fill in the VL server list from the rest of the string */ 65 /* fill in the VL server list from the rest of the string */
64 ret = -EINVAL;
65 do { 66 do {
66 unsigned a, b, c, d; 67 unsigned a, b, c, d;
67 68
@@ -70,18 +71,73 @@ struct afs_cell *afs_cell_create(const char *name, char *vllist)
70 *next++ = 0; 71 *next++ = 0;
71 72
72 if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) 73 if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
73 goto badaddr; 74 goto bad_address;
74 75
75 if (a > 255 || b > 255 || c > 255 || d > 255) 76 if (a > 255 || b > 255 || c > 255 || d > 255)
76 goto badaddr; 77 goto bad_address;
77 78
78 cell->vl_addrs[cell->vl_naddrs++].s_addr = 79 cell->vl_addrs[cell->vl_naddrs++].s_addr =
79 htonl((a << 24) | (b << 16) | (c << 8) | d); 80 htonl((a << 24) | (b << 16) | (c << 8) | d);
80 81
81 if (cell->vl_naddrs >= AFS_CELL_MAX_ADDRS) 82 } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next));
82 break; 83
84 /* create a key to represent an anonymous user */
85 memcpy(keyname, "afs@", 4);
86 dp = keyname + 4;
87 cp = cell->name;
88 do {
89 *dp++ = toupper(*cp);
90 } while (*cp++);
91 cell->anonymous_key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current,
92 KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
93 if (IS_ERR(cell->anonymous_key)) {
94 _debug("no key");
95 ret = PTR_ERR(cell->anonymous_key);
96 goto error;
97 }
98
99 ret = key_instantiate_and_link(cell->anonymous_key, NULL, 0,
100 NULL, NULL);
101 if (ret < 0) {
102 _debug("instantiate failed");
103 goto error;
104 }
105
106 _debug("anon key %p{%x}",
107 cell->anonymous_key, key_serial(cell->anonymous_key));
108
109 _leave(" = %p", cell);
110 return cell;
111
112bad_address:
113 printk(KERN_ERR "kAFS: bad VL server IP address\n");
114 ret = -EINVAL;
115error:
116 key_put(cell->anonymous_key);
117 kfree(cell);
118 _leave(" = %d", ret);
119 return ERR_PTR(ret);
120}
83 121
84 } while ((vllist = next)); 122/*
123 * create a cell record
124 * - "name" is the name of the cell
125 * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format
126 */
127struct afs_cell *afs_cell_create(const char *name, char *vllist)
128{
129 struct afs_cell *cell;
130 int ret;
131
132 _enter("%s,%s", name, vllist);
133
134 cell = afs_cell_alloc(name, vllist);
135 if (IS_ERR(cell)) {
136 _leave(" = %ld", PTR_ERR(cell));
137 return cell;
138 }
139
140 down_write(&afs_cells_sem);
85 141
86 /* add a proc directory for this cell */ 142 /* add a proc directory for this cell */
87 ret = afs_proc_cell_setup(cell); 143 ret = afs_proc_cell_setup(cell);
@@ -109,10 +165,9 @@ struct afs_cell *afs_cell_create(const char *name, char *vllist)
109 _leave(" = %p", cell); 165 _leave(" = %p", cell);
110 return cell; 166 return cell;
111 167
112badaddr:
113 printk(KERN_ERR "kAFS: bad VL server IP address\n");
114error: 168error:
115 up_write(&afs_cells_sem); 169 up_write(&afs_cells_sem);
170 key_put(cell->anonymous_key);
116 kfree(cell); 171 kfree(cell);
117 _leave(" = %d", ret); 172 _leave(" = %d", ret);
118 return ERR_PTR(ret); 173 return ERR_PTR(ret);
@@ -301,6 +356,7 @@ static void afs_cell_destroy(struct afs_cell *cell)
301 cachefs_relinquish_cookie(cell->cache, 0); 356 cachefs_relinquish_cookie(cell->cache, 0);
302#endif 357#endif
303 358
359 key_put(cell->anonymous_key);
304 kfree(cell); 360 kfree(cell);
305 361
306 _leave(" [destroyed]"); 362 _leave(" [destroyed]");
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index c7141175391b..c3ec57a237bf 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -28,6 +28,7 @@ static void afs_cm_destructor(struct afs_call *);
28 * CB.CallBack operation type 28 * CB.CallBack operation type
29 */ 29 */
30static const struct afs_call_type afs_SRXCBCallBack = { 30static const struct afs_call_type afs_SRXCBCallBack = {
31 .name = "CB.CallBack",
31 .deliver = afs_deliver_cb_callback, 32 .deliver = afs_deliver_cb_callback,
32 .abort_to_error = afs_abort_to_error, 33 .abort_to_error = afs_abort_to_error,
33 .destructor = afs_cm_destructor, 34 .destructor = afs_cm_destructor,
@@ -37,6 +38,7 @@ static const struct afs_call_type afs_SRXCBCallBack = {
37 * CB.InitCallBackState operation type 38 * CB.InitCallBackState operation type
38 */ 39 */
39static const struct afs_call_type afs_SRXCBInitCallBackState = { 40static const struct afs_call_type afs_SRXCBInitCallBackState = {
41 .name = "CB.InitCallBackState",
40 .deliver = afs_deliver_cb_init_call_back_state, 42 .deliver = afs_deliver_cb_init_call_back_state,
41 .abort_to_error = afs_abort_to_error, 43 .abort_to_error = afs_abort_to_error,
42 .destructor = afs_cm_destructor, 44 .destructor = afs_cm_destructor,
@@ -46,6 +48,7 @@ static const struct afs_call_type afs_SRXCBInitCallBackState = {
46 * CB.Probe operation type 48 * CB.Probe operation type
47 */ 49 */
48static const struct afs_call_type afs_SRXCBProbe = { 50static const struct afs_call_type afs_SRXCBProbe = {
51 .name = "CB.Probe",
49 .deliver = afs_deliver_cb_probe, 52 .deliver = afs_deliver_cb_probe,
50 .abort_to_error = afs_abort_to_error, 53 .abort_to_error = afs_abort_to_error,
51 .destructor = afs_cm_destructor, 54 .destructor = afs_cm_destructor,
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;
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 6990327e75dd..101bbb8c0d8b 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -17,17 +17,23 @@
17#include <linux/pagemap.h> 17#include <linux/pagemap.h>
18#include "internal.h" 18#include "internal.h"
19 19
20#if 0
21static int afs_file_open(struct inode *inode, struct file *file);
22static int afs_file_release(struct inode *inode, struct file *file);
23#endif
24
25static int afs_file_readpage(struct file *file, struct page *page); 20static int afs_file_readpage(struct file *file, struct page *page);
26static void afs_file_invalidatepage(struct page *page, unsigned long offset); 21static void afs_file_invalidatepage(struct page *page, unsigned long offset);
27static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); 22static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
28 23
24const struct file_operations afs_file_operations = {
25 .open = afs_open,
26 .release = afs_release,
27 .llseek = generic_file_llseek,
28 .read = do_sync_read,
29 .aio_read = generic_file_aio_read,
30 .mmap = generic_file_readonly_mmap,
31 .sendfile = generic_file_sendfile,
32};
33
29const struct inode_operations afs_file_inode_operations = { 34const struct inode_operations afs_file_inode_operations = {
30 .getattr = afs_inode_getattr, 35 .getattr = afs_inode_getattr,
36 .permission = afs_permission,
31}; 37};
32 38
33const struct address_space_operations afs_fs_aops = { 39const struct address_space_operations afs_fs_aops = {
@@ -38,6 +44,41 @@ const struct address_space_operations afs_fs_aops = {
38}; 44};
39 45
40/* 46/*
47 * open an AFS file or directory and attach a key to it
48 */
49int afs_open(struct inode *inode, struct file *file)
50{
51 struct afs_vnode *vnode = AFS_FS_I(inode);
52 struct key *key;
53
54 _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
55
56 key = afs_request_key(vnode->volume->cell);
57 if (IS_ERR(key)) {
58 _leave(" = %ld [key]", PTR_ERR(key));
59 return PTR_ERR(key);
60 }
61
62 file->private_data = key;
63 _leave(" = 0");
64 return 0;
65}
66
67/*
68 * release an AFS file or directory and discard its key
69 */
70int afs_release(struct inode *inode, struct file *file)
71{
72 struct afs_vnode *vnode = AFS_FS_I(inode);
73
74 _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
75
76 key_put(file->private_data);
77 _leave(" = 0");
78 return 0;
79}
80
81/*
41 * deal with notification that a page was read from the cache 82 * deal with notification that a page was read from the cache
42 */ 83 */
43#ifdef AFS_CACHING_SUPPORT 84#ifdef AFS_CACHING_SUPPORT
@@ -79,13 +120,18 @@ static int afs_file_readpage(struct file *file, struct page *page)
79{ 120{
80 struct afs_vnode *vnode; 121 struct afs_vnode *vnode;
81 struct inode *inode; 122 struct inode *inode;
123 struct key *key;
82 size_t len; 124 size_t len;
83 off_t offset; 125 off_t offset;
84 int ret; 126 int ret;
85 127
86 inode = page->mapping->host; 128 inode = page->mapping->host;
87 129
88 _enter("{%lu},{%lu}", inode->i_ino, page->index); 130 ASSERT(file != NULL);
131 key = file->private_data;
132 ASSERT(key != NULL);
133
134 _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index);
89 135
90 vnode = AFS_FS_I(inode); 136 vnode = AFS_FS_I(inode);
91 137
@@ -124,7 +170,7 @@ static int afs_file_readpage(struct file *file, struct page *page)
124 170
125 /* read the contents of the file from the server into the 171 /* read the contents of the file from the server into the
126 * page */ 172 * page */
127 ret = afs_vnode_fetch_data(vnode, offset, len, page); 173 ret = afs_vnode_fetch_data(vnode, key, offset, len, page);
128 if (ret < 0) { 174 if (ret < 0) {
129 if (ret == -ENOENT) { 175 if (ret == -ENOENT) {
130 _debug("got NOENT from server" 176 _debug("got NOENT from server"
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 167ca615c2e6..321b489aa90f 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -148,6 +148,7 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call,
148 * FS.FetchStatus operation type 148 * FS.FetchStatus operation type
149 */ 149 */
150static const struct afs_call_type afs_RXFSFetchStatus = { 150static const struct afs_call_type afs_RXFSFetchStatus = {
151 .name = "FS.FetchStatus",
151 .deliver = afs_deliver_fs_fetch_status, 152 .deliver = afs_deliver_fs_fetch_status,
152 .abort_to_error = afs_abort_to_error, 153 .abort_to_error = afs_abort_to_error,
153 .destructor = afs_flat_call_destructor, 154 .destructor = afs_flat_call_destructor,
@@ -157,6 +158,7 @@ static const struct afs_call_type afs_RXFSFetchStatus = {
157 * fetch the status information for a file 158 * fetch the status information for a file
158 */ 159 */
159int afs_fs_fetch_file_status(struct afs_server *server, 160int afs_fs_fetch_file_status(struct afs_server *server,
161 struct key *key,
160 struct afs_vnode *vnode, 162 struct afs_vnode *vnode,
161 struct afs_volsync *volsync, 163 struct afs_volsync *volsync,
162 const struct afs_wait_mode *wait_mode) 164 const struct afs_wait_mode *wait_mode)
@@ -164,12 +166,13 @@ int afs_fs_fetch_file_status(struct afs_server *server,
164 struct afs_call *call; 166 struct afs_call *call;
165 __be32 *bp; 167 __be32 *bp;
166 168
167 _enter(""); 169 _enter(",%x,,,", key_serial(key));
168 170
169 call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, 120); 171 call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, 120);
170 if (!call) 172 if (!call)
171 return -ENOMEM; 173 return -ENOMEM;
172 174
175 call->key = key;
173 call->reply = vnode; 176 call->reply = vnode;
174 call->reply2 = volsync; 177 call->reply2 = volsync;
175 call->service_id = FS_SERVICE; 178 call->service_id = FS_SERVICE;
@@ -279,6 +282,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
279 * FS.FetchData operation type 282 * FS.FetchData operation type
280 */ 283 */
281static const struct afs_call_type afs_RXFSFetchData = { 284static const struct afs_call_type afs_RXFSFetchData = {
285 .name = "FS.FetchData",
282 .deliver = afs_deliver_fs_fetch_data, 286 .deliver = afs_deliver_fs_fetch_data,
283 .abort_to_error = afs_abort_to_error, 287 .abort_to_error = afs_abort_to_error,
284 .destructor = afs_flat_call_destructor, 288 .destructor = afs_flat_call_destructor,
@@ -288,6 +292,7 @@ static const struct afs_call_type afs_RXFSFetchData = {
288 * fetch data from a file 292 * fetch data from a file
289 */ 293 */
290int afs_fs_fetch_data(struct afs_server *server, 294int afs_fs_fetch_data(struct afs_server *server,
295 struct key *key,
291 struct afs_vnode *vnode, 296 struct afs_vnode *vnode,
292 off_t offset, size_t length, 297 off_t offset, size_t length,
293 struct page *buffer, 298 struct page *buffer,
@@ -303,6 +308,7 @@ int afs_fs_fetch_data(struct afs_server *server,
303 if (!call) 308 if (!call)
304 return -ENOMEM; 309 return -ENOMEM;
305 310
311 call->key = key;
306 call->reply = vnode; 312 call->reply = vnode;
307 call->reply2 = volsync; 313 call->reply2 = volsync;
308 call->reply3 = buffer; 314 call->reply3 = buffer;
@@ -338,6 +344,7 @@ static int afs_deliver_fs_give_up_callbacks(struct afs_call *call,
338 * FS.GiveUpCallBacks operation type 344 * FS.GiveUpCallBacks operation type
339 */ 345 */
340static const struct afs_call_type afs_RXFSGiveUpCallBacks = { 346static const struct afs_call_type afs_RXFSGiveUpCallBacks = {
347 .name = "FS.GiveUpCallBacks",
341 .deliver = afs_deliver_fs_give_up_callbacks, 348 .deliver = afs_deliver_fs_give_up_callbacks,
342 .abort_to_error = afs_abort_to_error, 349 .abort_to_error = afs_abort_to_error,
343 .destructor = afs_flat_call_destructor, 350 .destructor = afs_flat_call_destructor,
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 18863315211f..227336228299 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -29,7 +29,7 @@ struct afs_iget_data {
29/* 29/*
30 * map the AFS file status to the inode member variables 30 * map the AFS file status to the inode member variables
31 */ 31 */
32static int afs_inode_map_status(struct afs_vnode *vnode) 32static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
33{ 33{
34 struct inode *inode = AFS_VNODE_TO_I(vnode); 34 struct inode *inode = AFS_VNODE_TO_I(vnode);
35 35
@@ -44,7 +44,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
44 case AFS_FTYPE_FILE: 44 case AFS_FTYPE_FILE:
45 inode->i_mode = S_IFREG | vnode->status.mode; 45 inode->i_mode = S_IFREG | vnode->status.mode;
46 inode->i_op = &afs_file_inode_operations; 46 inode->i_op = &afs_file_inode_operations;
47 inode->i_fop = &generic_ro_fops; 47 inode->i_fop = &afs_file_operations;
48 break; 48 break;
49 case AFS_FTYPE_DIR: 49 case AFS_FTYPE_DIR:
50 inode->i_mode = S_IFDIR | vnode->status.mode; 50 inode->i_mode = S_IFDIR | vnode->status.mode;
@@ -73,7 +73,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
73 73
74 /* check to see whether a symbolic link is really a mountpoint */ 74 /* check to see whether a symbolic link is really a mountpoint */
75 if (vnode->status.type == AFS_FTYPE_SYMLINK) { 75 if (vnode->status.type == AFS_FTYPE_SYMLINK) {
76 afs_mntpt_check_symlink(vnode); 76 afs_mntpt_check_symlink(vnode, key);
77 77
78 if (test_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags)) { 78 if (test_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags)) {
79 inode->i_mode = S_IFDIR | vnode->status.mode; 79 inode->i_mode = S_IFDIR | vnode->status.mode;
@@ -115,7 +115,8 @@ static int afs_iget5_set(struct inode *inode, void *opaque)
115/* 115/*
116 * inode retrieval 116 * inode retrieval
117 */ 117 */
118inline struct inode *afs_iget(struct super_block *sb, struct afs_fid *fid) 118inline struct inode *afs_iget(struct super_block *sb, struct key *key,
119 struct afs_fid *fid)
119{ 120{
120 struct afs_iget_data data = { .fid = *fid }; 121 struct afs_iget_data data = { .fid = *fid };
121 struct afs_super_info *as; 122 struct afs_super_info *as;
@@ -157,10 +158,10 @@ inline struct inode *afs_iget(struct super_block *sb, struct afs_fid *fid)
157 158
158 /* okay... it's a new inode */ 159 /* okay... it's a new inode */
159 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags); 160 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
160 ret = afs_vnode_fetch_status(vnode); 161 ret = afs_vnode_fetch_status(vnode, NULL, key);
161 if (ret < 0) 162 if (ret < 0)
162 goto bad_inode; 163 goto bad_inode;
163 ret = afs_inode_map_status(vnode); 164 ret = afs_inode_map_status(vnode, key);
164 if (ret < 0) 165 if (ret < 0)
165 goto bad_inode; 166 goto bad_inode;
166 167
@@ -201,6 +202,7 @@ int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
201 */ 202 */
202void afs_clear_inode(struct inode *inode) 203void afs_clear_inode(struct inode *inode)
203{ 204{
205 struct afs_permits *permits;
204 struct afs_vnode *vnode; 206 struct afs_vnode *vnode;
205 207
206 vnode = AFS_FS_I(inode); 208 vnode = AFS_FS_I(inode);
@@ -233,5 +235,12 @@ void afs_clear_inode(struct inode *inode)
233 vnode->cache = NULL; 235 vnode->cache = NULL;
234#endif 236#endif
235 237
238 mutex_lock(&vnode->permits_lock);
239 permits = vnode->permits;
240 rcu_assign_pointer(vnode->permits, NULL);
241 mutex_unlock(&vnode->permits_lock);
242 if (permits)
243 call_rcu(&permits->rcu, afs_zap_permits);
244
236 _leave(""); 245 _leave("");
237} 246}
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index afc6f0f30259..8bed2429d01f 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -15,6 +15,7 @@
15#include <linux/pagemap.h> 15#include <linux/pagemap.h>
16#include <linux/skbuff.h> 16#include <linux/skbuff.h>
17#include <linux/rxrpc.h> 17#include <linux/rxrpc.h>
18#include <linux/key.h>
18#include "afs.h" 19#include "afs.h"
19#include "afs_vl.h" 20#include "afs_vl.h"
20 21
@@ -32,6 +33,17 @@ typedef enum {
32 AFS_VL_UNCERTAIN, /* uncertain state (update failed) */ 33 AFS_VL_UNCERTAIN, /* uncertain state (update failed) */
33} __attribute__((packed)) afs_vlocation_state_t; 34} __attribute__((packed)) afs_vlocation_state_t;
34 35
36struct afs_mount_params {
37 bool rwpath; /* T if the parent should be considered R/W */
38 bool force; /* T to force cell type */
39 afs_voltype_t type; /* type of volume requested */
40 int volnamesz; /* size of volume name */
41 const char *volname; /* name of volume to mount */
42 struct afs_cell *cell; /* cell in which to find volume */
43 struct afs_volume *volume; /* volume record */
44 struct key *key; /* key to use for secure mounting */
45};
46
35/* 47/*
36 * definition of how to wait for the completion of an operation 48 * definition of how to wait for the completion of an operation
37 */ 49 */
@@ -95,6 +107,8 @@ struct afs_call {
95}; 107};
96 108
97struct afs_call_type { 109struct afs_call_type {
110 const char *name;
111
98 /* deliver request or reply data to an call 112 /* deliver request or reply data to an call
99 * - returning an error will cause the call to be aborted 113 * - returning an error will cause the call to be aborted
100 */ 114 */
@@ -128,8 +142,8 @@ extern struct file_system_type afs_fs_type;
128 * entry in the cached cell catalogue 142 * entry in the cached cell catalogue
129 */ 143 */
130struct afs_cache_cell { 144struct afs_cache_cell {
131 char name[64]; /* cell name (padded with NULs) */ 145 char name[AFS_MAXCELLNAME]; /* cell name (padded with NULs) */
132 struct in_addr vl_servers[15]; /* cached cell VL servers */ 146 struct in_addr vl_servers[15]; /* cached cell VL servers */
133}; 147};
134 148
135/* 149/*
@@ -138,6 +152,7 @@ struct afs_cache_cell {
138struct afs_cell { 152struct afs_cell {
139 atomic_t usage; 153 atomic_t usage;
140 struct list_head link; /* main cell list link */ 154 struct list_head link; /* main cell list link */
155 struct key *anonymous_key; /* anonymous user key for this cell */
141 struct list_head proc_link; /* /proc cell list link */ 156 struct list_head proc_link; /* /proc cell list link */
142 struct proc_dir_entry *proc_dir; /* /proc dir for this cell */ 157 struct proc_dir_entry *proc_dir; /* /proc dir for this cell */
143#ifdef AFS_CACHING_SUPPORT 158#ifdef AFS_CACHING_SUPPORT
@@ -163,7 +178,9 @@ struct afs_cell {
163 * entry in the cached volume location catalogue 178 * entry in the cached volume location catalogue
164 */ 179 */
165struct afs_cache_vlocation { 180struct afs_cache_vlocation {
166 uint8_t name[64 + 1]; /* volume name (lowercase, padded with NULs) */ 181 /* volume name (lowercase, padded with NULs) */
182 uint8_t name[AFS_MAXVOLNAME + 1];
183
167 uint8_t nservers; /* number of entries used in servers[] */ 184 uint8_t nservers; /* number of entries used in servers[] */
168 uint8_t vidmask; /* voltype mask for vid[] */ 185 uint8_t vidmask; /* voltype mask for vid[] */
169 uint8_t srvtmask[8]; /* voltype masks for servers[] */ 186 uint8_t srvtmask[8]; /* voltype masks for servers[] */
@@ -281,7 +298,8 @@ struct afs_vnode {
281#ifdef AFS_CACHING_SUPPORT 298#ifdef AFS_CACHING_SUPPORT
282 struct cachefs_cookie *cache; /* caching cookie */ 299 struct cachefs_cookie *cache; /* caching cookie */
283#endif 300#endif
284 301 struct afs_permits *permits; /* cache of permits so far obtained */
302 struct mutex permits_lock; /* lock for altering permits list */
285 wait_queue_head_t update_waitq; /* status fetch waitqueue */ 303 wait_queue_head_t update_waitq; /* status fetch waitqueue */
286 unsigned update_cnt; /* number of outstanding ops that will update the 304 unsigned update_cnt; /* number of outstanding ops that will update the
287 * status */ 305 * status */
@@ -296,12 +314,13 @@ struct afs_vnode {
296#define AFS_VNODE_DIR_CHANGED 6 /* set if vnode's parent dir metadata changed */ 314#define AFS_VNODE_DIR_CHANGED 6 /* set if vnode's parent dir metadata changed */
297#define AFS_VNODE_DIR_MODIFIED 7 /* set if vnode's parent dir data modified */ 315#define AFS_VNODE_DIR_MODIFIED 7 /* set if vnode's parent dir data modified */
298 316
317 long acl_order; /* ACL check count (callback break count) */
318
299 /* outstanding callback notification on this file */ 319 /* outstanding callback notification on this file */
300 struct rb_node server_rb; /* link in server->fs_vnodes */ 320 struct rb_node server_rb; /* link in server->fs_vnodes */
301 struct rb_node cb_promise; /* link in server->cb_promises */ 321 struct rb_node cb_promise; /* link in server->cb_promises */
302 struct work_struct cb_broken_work; /* work to be done on callback break */ 322 struct work_struct cb_broken_work; /* work to be done on callback break */
303 struct mutex cb_broken_lock; /* lock against multiple attempts to fix break */ 323 struct mutex cb_broken_lock; /* lock against multiple attempts to fix break */
304// struct list_head cb_hash_link; /* link in master callback hash */
305 time_t cb_expires; /* time at which callback expires */ 324 time_t cb_expires; /* time at which callback expires */
306 time_t cb_expires_at; /* time used to order cb_promise */ 325 time_t cb_expires_at; /* time used to order cb_promise */
307 unsigned cb_version; /* callback version */ 326 unsigned cb_version; /* callback version */
@@ -310,6 +329,23 @@ struct afs_vnode {
310 bool cb_promised; /* true if promise still holds */ 329 bool cb_promised; /* true if promise still holds */
311}; 330};
312 331
332/*
333 * cached security record for one user's attempt to access a vnode
334 */
335struct afs_permit {
336 struct key *key; /* RxRPC ticket holding a security context */
337 afs_access_t access_mask; /* access mask for this key */
338};
339
340/*
341 * cache of security records from attempts to access a vnode
342 */
343struct afs_permits {
344 struct rcu_head rcu; /* disposal procedure */
345 int count; /* number of records */
346 struct afs_permit permits[0]; /* the permits so far examined */
347};
348
313/*****************************************************************************/ 349/*****************************************************************************/
314/* 350/*
315 * callback.c 351 * callback.c
@@ -352,11 +388,17 @@ extern bool afs_cm_incoming_call(struct afs_call *);
352extern const struct inode_operations afs_dir_inode_operations; 388extern const struct inode_operations afs_dir_inode_operations;
353extern const struct file_operations afs_dir_file_operations; 389extern const struct file_operations afs_dir_file_operations;
354 390
391extern int afs_permission(struct inode *, int, struct nameidata *);
392
355/* 393/*
356 * file.c 394 * file.c
357 */ 395 */
358extern const struct address_space_operations afs_fs_aops; 396extern const struct address_space_operations afs_fs_aops;
359extern const struct inode_operations afs_file_inode_operations; 397extern const struct inode_operations afs_file_inode_operations;
398extern const struct file_operations afs_file_operations;
399
400extern int afs_open(struct inode *, struct file *);
401extern int afs_release(struct inode *, struct file *);
360 402
361#ifdef AFS_CACHING_SUPPORT 403#ifdef AFS_CACHING_SUPPORT
362extern int afs_cache_get_page_cookie(struct page *, struct cachefs_page **); 404extern int afs_cache_get_page_cookie(struct page *, struct cachefs_page **);
@@ -365,22 +407,24 @@ extern int afs_cache_get_page_cookie(struct page *, struct cachefs_page **);
365/* 407/*
366 * fsclient.c 408 * fsclient.c
367 */ 409 */
368extern int afs_fs_fetch_file_status(struct afs_server *, 410extern int afs_fs_fetch_file_status(struct afs_server *, struct key *,
369 struct afs_vnode *, 411 struct afs_vnode *, struct afs_volsync *,
370 struct afs_volsync *,
371 const struct afs_wait_mode *); 412 const struct afs_wait_mode *);
372extern int afs_fs_give_up_callbacks(struct afs_server *, 413extern int afs_fs_give_up_callbacks(struct afs_server *,
373 const struct afs_wait_mode *); 414 const struct afs_wait_mode *);
374extern int afs_fs_fetch_data(struct afs_server *, struct afs_vnode *, off_t, 415extern int afs_fs_fetch_data(struct afs_server *, struct key *,
375 size_t, struct page *, struct afs_volsync *, 416 struct afs_vnode *, off_t, size_t, struct page *,
417 struct afs_volsync *,
376 const struct afs_wait_mode *); 418 const struct afs_wait_mode *);
377 419
378/* 420/*
379 * inode.c 421 * inode.c
380 */ 422 */
381extern struct inode *afs_iget(struct super_block *, struct afs_fid *); 423extern struct inode *afs_iget(struct super_block *, struct key *,
424 struct afs_fid *);
382extern int afs_inode_getattr(struct vfsmount *, struct dentry *, 425extern int afs_inode_getattr(struct vfsmount *, struct dentry *,
383 struct kstat *); 426 struct kstat *);
427extern void afs_zap_permits(struct rcu_head *);
384extern void afs_clear_inode(struct inode *); 428extern void afs_clear_inode(struct inode *);
385 429
386/* 430/*
@@ -402,17 +446,11 @@ extern const struct inode_operations afs_mntpt_inode_operations;
402extern const struct file_operations afs_mntpt_file_operations; 446extern const struct file_operations afs_mntpt_file_operations;
403extern unsigned long afs_mntpt_expiry_timeout; 447extern unsigned long afs_mntpt_expiry_timeout;
404 448
405extern int afs_mntpt_check_symlink(struct afs_vnode *); 449extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *);
406extern void afs_mntpt_kill_timer(void); 450extern void afs_mntpt_kill_timer(void);
407extern void afs_umount_begin(struct vfsmount *, int); 451extern void afs_umount_begin(struct vfsmount *, int);
408 452
409/* 453/*
410 * super.c
411 */
412extern int afs_fs_init(void);
413extern void afs_fs_exit(void);
414
415/*
416 * proc.c 454 * proc.c
417 */ 455 */
418extern int afs_proc_init(void); 456extern int afs_proc_init(void);
@@ -436,6 +474,14 @@ extern int afs_extract_data(struct afs_call *, struct sk_buff *, bool, void *,
436 size_t); 474 size_t);
437 475
438/* 476/*
477 * security.c
478 */
479extern void afs_clear_permits(struct afs_vnode *);
480extern void afs_cache_permit(struct afs_vnode *, struct key *, long);
481extern struct key *afs_request_key(struct afs_cell *);
482extern int afs_permission(struct inode *, int, struct nameidata *);
483
484/*
439 * server.c 485 * server.c
440 */ 486 */
441extern spinlock_t afs_server_peer_lock; 487extern spinlock_t afs_server_peer_lock;
@@ -449,16 +495,23 @@ extern void afs_put_server(struct afs_server *);
449extern void __exit afs_purge_servers(void); 495extern void __exit afs_purge_servers(void);
450 496
451/* 497/*
498 * super.c
499 */
500extern int afs_fs_init(void);
501extern void afs_fs_exit(void);
502
503/*
452 * vlclient.c 504 * vlclient.c
453 */ 505 */
454#ifdef AFS_CACHING_SUPPORT 506#ifdef AFS_CACHING_SUPPORT
455extern struct cachefs_index_def afs_vlocation_cache_index_def; 507extern struct cachefs_index_def afs_vlocation_cache_index_def;
456#endif 508#endif
457 509
458extern int afs_vl_get_entry_by_name(struct in_addr *, const char *, 510extern int afs_vl_get_entry_by_name(struct in_addr *, struct key *,
459 struct afs_cache_vlocation *, 511 const char *, struct afs_cache_vlocation *,
460 const struct afs_wait_mode *); 512 const struct afs_wait_mode *);
461extern int afs_vl_get_entry_by_id(struct in_addr *, afs_volid_t, afs_voltype_t, 513extern int afs_vl_get_entry_by_id(struct in_addr *, struct key *,
514 afs_volid_t, afs_voltype_t,
462 struct afs_cache_vlocation *, 515 struct afs_cache_vlocation *,
463 const struct afs_wait_mode *); 516 const struct afs_wait_mode *);
464 517
@@ -469,6 +522,7 @@ extern int afs_vl_get_entry_by_id(struct in_addr *, afs_volid_t, afs_voltype_t,
469 522
470extern int __init afs_vlocation_update_init(void); 523extern int __init afs_vlocation_update_init(void);
471extern struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *, 524extern struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *,
525 struct key *,
472 const char *, size_t); 526 const char *, size_t);
473extern void afs_put_vlocation(struct afs_vlocation *); 527extern void afs_put_vlocation(struct afs_vlocation *);
474extern void __exit afs_vlocation_purge(void); 528extern void __exit afs_vlocation_purge(void);
@@ -492,9 +546,10 @@ static inline struct inode *AFS_VNODE_TO_I(struct afs_vnode *vnode)
492 return &vnode->vfs_inode; 546 return &vnode->vfs_inode;
493} 547}
494 548
495extern int afs_vnode_fetch_status(struct afs_vnode *); 549extern int afs_vnode_fetch_status(struct afs_vnode *, struct afs_vnode *,
496extern int afs_vnode_fetch_data(struct afs_vnode *vnode, off_t, size_t, 550 struct key *);
497 struct page *); 551extern int afs_vnode_fetch_data(struct afs_vnode *, struct key *,
552 off_t, size_t, struct page *);
498 553
499/* 554/*
500 * volume.c 555 * volume.c
@@ -506,8 +561,7 @@ extern struct cachefs_index_def afs_volume_cache_index_def;
506#define afs_get_volume(V) do { atomic_inc(&(V)->usage); } while(0) 561#define afs_get_volume(V) do { atomic_inc(&(V)->usage); } while(0)
507 562
508extern void afs_put_volume(struct afs_volume *); 563extern void afs_put_volume(struct afs_volume *);
509extern struct afs_volume *afs_volume_lookup(const char *, struct afs_cell *, 564extern struct afs_volume *afs_volume_lookup(struct afs_mount_params *);
510 int);
511extern struct afs_server *afs_volume_pick_fileserver(struct afs_vnode *); 565extern struct afs_server *afs_volume_pick_fileserver(struct afs_vnode *);
512extern int afs_volume_release_fileserver(struct afs_vnode *, 566extern int afs_volume_release_fileserver(struct afs_vnode *,
513 struct afs_server *, int); 567 struct afs_server *, int);
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 08c11a0b66bd..b905ae37f912 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -48,8 +48,11 @@ unsigned long afs_mntpt_expiry_timeout = 10 * 60;
48 * check a symbolic link to see whether it actually encodes a mountpoint 48 * check a symbolic link to see whether it actually encodes a mountpoint
49 * - sets the AFS_VNODE_MOUNTPOINT flag on the vnode appropriately 49 * - sets the AFS_VNODE_MOUNTPOINT flag on the vnode appropriately
50 */ 50 */
51int afs_mntpt_check_symlink(struct afs_vnode *vnode) 51int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
52{ 52{
53 struct file file = {
54 .private_data = key,
55 };
53 struct page *page; 56 struct page *page;
54 size_t size; 57 size_t size;
55 char *buf; 58 char *buf;
@@ -58,7 +61,7 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode)
58 _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique); 61 _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique);
59 62
60 /* read the contents of the symlink into the pagecache */ 63 /* read the contents of the symlink into the pagecache */
61 page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, NULL); 64 page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, &file);
62 if (IS_ERR(page)) { 65 if (IS_ERR(page)) {
63 ret = PTR_ERR(page); 66 ret = PTR_ERR(page);
64 goto out; 67 goto out;
@@ -214,7 +217,7 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
214 struct vfsmount *newmnt; 217 struct vfsmount *newmnt;
215 int err; 218 int err;
216 219
217 _enter("%p{%s},{%s:%p{%s}}", 220 _enter("%p{%s},{%s:%p{%s},}",
218 dentry, 221 dentry,
219 dentry->d_name.name, 222 dentry->d_name.name,
220 nd->mnt->mnt_devname, 223 nd->mnt->mnt_devname,
@@ -234,7 +237,8 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
234 err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts); 237 err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts);
235 switch (err) { 238 switch (err) {
236 case 0: 239 case 0:
237 path_release(nd); 240 mntput(nd->mnt);
241 dput(nd->dentry);
238 nd->mnt = newmnt; 242 nd->mnt = newmnt;
239 nd->dentry = dget(newmnt->mnt_root); 243 nd->dentry = dget(newmnt->mnt_root);
240 schedule_delayed_work(&afs_mntpt_expiry_timer, 244 schedule_delayed_work(&afs_mntpt_expiry_timer,
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index b92774231b3c..e86c527d87a1 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -17,6 +17,8 @@
17 17
18static struct socket *afs_socket; /* my RxRPC socket */ 18static struct socket *afs_socket; /* my RxRPC socket */
19static struct workqueue_struct *afs_async_calls; 19static struct workqueue_struct *afs_async_calls;
20static atomic_t afs_outstanding_calls;
21static atomic_t afs_outstanding_skbs;
20 22
21static void afs_wake_up_call_waiter(struct afs_call *); 23static void afs_wake_up_call_waiter(struct afs_call *);
22static int afs_wait_for_call_to_complete(struct afs_call *); 24static int afs_wait_for_call_to_complete(struct afs_call *);
@@ -45,6 +47,7 @@ static const struct afs_wait_mode afs_async_incoming_call = {
45 47
46/* asynchronous incoming call initial processing */ 48/* asynchronous incoming call initial processing */
47static const struct afs_call_type afs_RXCMxxxx = { 49static const struct afs_call_type afs_RXCMxxxx = {
50 .name = "CB.xxxx",
48 .deliver = afs_deliver_cm_op_id, 51 .deliver = afs_deliver_cm_op_id,
49 .abort_to_error = afs_abort_to_error, 52 .abort_to_error = afs_abort_to_error,
50}; 53};
@@ -118,10 +121,67 @@ void afs_close_socket(void)
118 121
119 _debug("dework"); 122 _debug("dework");
120 destroy_workqueue(afs_async_calls); 123 destroy_workqueue(afs_async_calls);
124
125 ASSERTCMP(atomic_read(&afs_outstanding_skbs), ==, 0);
126 ASSERTCMP(atomic_read(&afs_outstanding_calls), ==, 0);
121 _leave(""); 127 _leave("");
122} 128}
123 129
124/* 130/*
131 * note that the data in a socket buffer is now delivered and that the buffer
132 * should be freed
133 */
134static void afs_data_delivered(struct sk_buff *skb)
135{
136 if (!skb) {
137 _debug("DLVR NULL [%d]", atomic_read(&afs_outstanding_skbs));
138 dump_stack();
139 } else {
140 _debug("DLVR %p{%u} [%d]",
141 skb, skb->mark, atomic_read(&afs_outstanding_skbs));
142 if (atomic_dec_return(&afs_outstanding_skbs) == -1)
143 BUG();
144 rxrpc_kernel_data_delivered(skb);
145 }
146}
147
148/*
149 * free a socket buffer
150 */
151static void afs_free_skb(struct sk_buff *skb)
152{
153 if (!skb) {
154 _debug("FREE NULL [%d]", atomic_read(&afs_outstanding_skbs));
155 dump_stack();
156 } else {
157 _debug("FREE %p{%u} [%d]",
158 skb, skb->mark, atomic_read(&afs_outstanding_skbs));
159 if (atomic_dec_return(&afs_outstanding_skbs) == -1)
160 BUG();
161 rxrpc_kernel_free_skb(skb);
162 }
163}
164
165/*
166 * free a call
167 */
168static void afs_free_call(struct afs_call *call)
169{
170 _debug("DONE %p{%s} [%d]",
171 call, call->type->name, atomic_read(&afs_outstanding_calls));
172 if (atomic_dec_return(&afs_outstanding_calls) == -1)
173 BUG();
174
175 ASSERTCMP(call->rxcall, ==, NULL);
176 ASSERT(!work_pending(&call->async_work));
177 ASSERT(skb_queue_empty(&call->rx_queue));
178 ASSERT(call->type->name != NULL);
179
180 kfree(call->request);
181 kfree(call);
182}
183
184/*
125 * allocate a call with flat request and reply buffers 185 * allocate a call with flat request and reply buffers
126 */ 186 */
127struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type, 187struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type,
@@ -133,30 +193,32 @@ struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type,
133 if (!call) 193 if (!call)
134 goto nomem_call; 194 goto nomem_call;
135 195
196 _debug("CALL %p{%s} [%d]",
197 call, type->name, atomic_read(&afs_outstanding_calls));
198 atomic_inc(&afs_outstanding_calls);
199
200 call->type = type;
201 call->request_size = request_size;
202 call->reply_max = reply_size;
203
136 if (request_size) { 204 if (request_size) {
137 call->request = kmalloc(request_size, GFP_NOFS); 205 call->request = kmalloc(request_size, GFP_NOFS);
138 if (!call->request) 206 if (!call->request)
139 goto nomem_request; 207 goto nomem_free;
140 } 208 }
141 209
142 if (reply_size) { 210 if (reply_size) {
143 call->buffer = kmalloc(reply_size, GFP_NOFS); 211 call->buffer = kmalloc(reply_size, GFP_NOFS);
144 if (!call->buffer) 212 if (!call->buffer)
145 goto nomem_buffer; 213 goto nomem_free;
146 } 214 }
147 215
148 call->type = type;
149 call->request_size = request_size;
150 call->reply_max = reply_size;
151
152 init_waitqueue_head(&call->waitq); 216 init_waitqueue_head(&call->waitq);
153 skb_queue_head_init(&call->rx_queue); 217 skb_queue_head_init(&call->rx_queue);
154 return call; 218 return call;
155 219
156nomem_buffer: 220nomem_free:
157 kfree(call->request); 221 afs_free_call(call);
158nomem_request:
159 kfree(call);
160nomem_call: 222nomem_call:
161 return NULL; 223 return NULL;
162} 224}
@@ -188,6 +250,12 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
188 250
189 _enter("%x,{%d},", addr->s_addr, ntohs(call->port)); 251 _enter("%x,{%d},", addr->s_addr, ntohs(call->port));
190 252
253 ASSERT(call->type != NULL);
254 ASSERT(call->type->name != NULL);
255
256 _debug("MAKE %p{%s} [%d]",
257 call, call->type->name, atomic_read(&afs_outstanding_calls));
258
191 call->wait_mode = wait_mode; 259 call->wait_mode = wait_mode;
192 INIT_WORK(&call->async_work, afs_process_async_call); 260 INIT_WORK(&call->async_work, afs_process_async_call);
193 261
@@ -203,6 +271,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
203 /* create a call */ 271 /* create a call */
204 rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key, 272 rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key,
205 (unsigned long) call, gfp); 273 (unsigned long) call, gfp);
274 call->key = NULL;
206 if (IS_ERR(rxcall)) { 275 if (IS_ERR(rxcall)) {
207 ret = PTR_ERR(rxcall); 276 ret = PTR_ERR(rxcall);
208 goto error_kill_call; 277 goto error_kill_call;
@@ -237,10 +306,10 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
237error_do_abort: 306error_do_abort:
238 rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT); 307 rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT);
239 rxrpc_kernel_end_call(rxcall); 308 rxrpc_kernel_end_call(rxcall);
309 call->rxcall = NULL;
240error_kill_call: 310error_kill_call:
241 call->type->destructor(call); 311 call->type->destructor(call);
242 ASSERT(skb_queue_empty(&call->rx_queue)); 312 afs_free_call(call);
243 kfree(call);
244 _leave(" = %d", ret); 313 _leave(" = %d", ret);
245 return ret; 314 return ret;
246} 315}
@@ -257,15 +326,19 @@ static void afs_rx_interceptor(struct sock *sk, unsigned long user_call_ID,
257 326
258 _enter("%p,,%u", call, skb->mark); 327 _enter("%p,,%u", call, skb->mark);
259 328
329 _debug("ICPT %p{%u} [%d]",
330 skb, skb->mark, atomic_read(&afs_outstanding_skbs));
331
260 ASSERTCMP(sk, ==, afs_socket->sk); 332 ASSERTCMP(sk, ==, afs_socket->sk);
333 atomic_inc(&afs_outstanding_skbs);
261 334
262 if (!call) { 335 if (!call) {
263 /* its an incoming call for our callback service */ 336 /* its an incoming call for our callback service */
264 __skb_queue_tail(&afs_incoming_calls, skb); 337 skb_queue_tail(&afs_incoming_calls, skb);
265 schedule_work(&afs_collect_incoming_call_work); 338 schedule_work(&afs_collect_incoming_call_work);
266 } else { 339 } else {
267 /* route the messages directly to the appropriate call */ 340 /* route the messages directly to the appropriate call */
268 __skb_queue_tail(&call->rx_queue, skb); 341 skb_queue_tail(&call->rx_queue, skb);
269 call->wait_mode->rx_wakeup(call); 342 call->wait_mode->rx_wakeup(call);
270 } 343 }
271 344
@@ -317,9 +390,9 @@ static void afs_deliver_to_call(struct afs_call *call)
317 call->state = AFS_CALL_ERROR; 390 call->state = AFS_CALL_ERROR;
318 break; 391 break;
319 } 392 }
320 rxrpc_kernel_data_delivered(skb); 393 afs_data_delivered(skb);
321 skb = NULL; 394 skb = NULL;
322 break; 395 continue;
323 case RXRPC_SKB_MARK_FINAL_ACK: 396 case RXRPC_SKB_MARK_FINAL_ACK:
324 _debug("Rcv ACK"); 397 _debug("Rcv ACK");
325 call->state = AFS_CALL_COMPLETE; 398 call->state = AFS_CALL_COMPLETE;
@@ -350,19 +423,19 @@ static void afs_deliver_to_call(struct afs_call *call)
350 break; 423 break;
351 } 424 }
352 425
353 rxrpc_kernel_free_skb(skb); 426 afs_free_skb(skb);
354 } 427 }
355 428
356 /* make sure the queue is empty if the call is done with (we might have 429 /* make sure the queue is empty if the call is done with (we might have
357 * aborted the call early because of an unmarshalling error) */ 430 * aborted the call early because of an unmarshalling error) */
358 if (call->state >= AFS_CALL_COMPLETE) { 431 if (call->state >= AFS_CALL_COMPLETE) {
359 while ((skb = skb_dequeue(&call->rx_queue))) 432 while ((skb = skb_dequeue(&call->rx_queue)))
360 rxrpc_kernel_free_skb(skb); 433 afs_free_skb(skb);
361 if (call->incoming) { 434 if (call->incoming) {
362 rxrpc_kernel_end_call(call->rxcall); 435 rxrpc_kernel_end_call(call->rxcall);
436 call->rxcall = NULL;
363 call->type->destructor(call); 437 call->type->destructor(call);
364 ASSERT(skb_queue_empty(&call->rx_queue)); 438 afs_free_call(call);
365 kfree(call);
366 } 439 }
367 } 440 }
368 441
@@ -409,14 +482,14 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
409 _debug("call incomplete"); 482 _debug("call incomplete");
410 rxrpc_kernel_abort_call(call->rxcall, RX_CALL_DEAD); 483 rxrpc_kernel_abort_call(call->rxcall, RX_CALL_DEAD);
411 while ((skb = skb_dequeue(&call->rx_queue))) 484 while ((skb = skb_dequeue(&call->rx_queue)))
412 rxrpc_kernel_free_skb(skb); 485 afs_free_skb(skb);
413 } 486 }
414 487
415 _debug("call complete"); 488 _debug("call complete");
416 rxrpc_kernel_end_call(call->rxcall); 489 rxrpc_kernel_end_call(call->rxcall);
490 call->rxcall = NULL;
417 call->type->destructor(call); 491 call->type->destructor(call);
418 ASSERT(skb_queue_empty(&call->rx_queue)); 492 afs_free_call(call);
419 kfree(call);
420 _leave(" = %d", ret); 493 _leave(" = %d", ret);
421 return ret; 494 return ret;
422} 495}
@@ -459,9 +532,7 @@ static void afs_delete_async_call(struct work_struct *work)
459 532
460 _enter(""); 533 _enter("");
461 534
462 ASSERT(skb_queue_empty(&call->rx_queue)); 535 afs_free_call(call);
463 ASSERT(!work_pending(&call->async_work));
464 kfree(call);
465 536
466 _leave(""); 537 _leave("");
467} 538}
@@ -489,6 +560,7 @@ static void afs_process_async_call(struct work_struct *work)
489 560
490 /* kill the call */ 561 /* kill the call */
491 rxrpc_kernel_end_call(call->rxcall); 562 rxrpc_kernel_end_call(call->rxcall);
563 call->rxcall = NULL;
492 if (call->type->destructor) 564 if (call->type->destructor)
493 call->type->destructor(call); 565 call->type->destructor(call);
494 566
@@ -526,7 +598,7 @@ static void afs_collect_incoming_call(struct work_struct *work)
526 _debug("new call"); 598 _debug("new call");
527 599
528 /* don't need the notification */ 600 /* don't need the notification */
529 rxrpc_kernel_free_skb(skb); 601 afs_free_skb(skb);
530 602
531 if (!call) { 603 if (!call) {
532 call = kzalloc(sizeof(struct afs_call), GFP_KERNEL); 604 call = kzalloc(sizeof(struct afs_call), GFP_KERNEL);
@@ -541,6 +613,11 @@ static void afs_collect_incoming_call(struct work_struct *work)
541 init_waitqueue_head(&call->waitq); 613 init_waitqueue_head(&call->waitq);
542 skb_queue_head_init(&call->rx_queue); 614 skb_queue_head_init(&call->rx_queue);
543 call->state = AFS_CALL_AWAIT_OP_ID; 615 call->state = AFS_CALL_AWAIT_OP_ID;
616
617 _debug("CALL %p{%s} [%d]",
618 call, call->type->name,
619 atomic_read(&afs_outstanding_calls));
620 atomic_inc(&afs_outstanding_calls);
544 } 621 }
545 622
546 rxcall = rxrpc_kernel_accept_call(afs_socket, 623 rxcall = rxrpc_kernel_accept_call(afs_socket,
@@ -551,7 +628,8 @@ static void afs_collect_incoming_call(struct work_struct *work)
551 } 628 }
552 } 629 }
553 630
554 kfree(call); 631 if (call)
632 afs_free_call(call);
555} 633}
556 634
557/* 635/*
@@ -629,8 +707,7 @@ void afs_send_empty_reply(struct afs_call *call)
629 rxrpc_kernel_end_call(call->rxcall); 707 rxrpc_kernel_end_call(call->rxcall);
630 call->rxcall = NULL; 708 call->rxcall = NULL;
631 call->type->destructor(call); 709 call->type->destructor(call);
632 ASSERT(skb_queue_empty(&call->rx_queue)); 710 afs_free_call(call);
633 kfree(call);
634 _leave(" [error]"); 711 _leave(" [error]");
635 return; 712 return;
636 } 713 }
diff --git a/fs/afs/security.c b/fs/afs/security.c
new file mode 100644
index 000000000000..cbdd7f7162fa
--- /dev/null
+++ b/fs/afs/security.c
@@ -0,0 +1,345 @@
1/* AFS security handling
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/init.h>
13#include <linux/slab.h>
14#include <linux/fs.h>
15#include <linux/ctype.h>
16#include <keys/rxrpc-type.h>
17#include "internal.h"
18
19/*
20 * get a key
21 */
22struct key *afs_request_key(struct afs_cell *cell)
23{
24 struct key *key;
25
26 _enter("{%x}", key_serial(cell->anonymous_key));
27
28 _debug("key %s", cell->anonymous_key->description);
29 key = request_key(&key_type_rxrpc, cell->anonymous_key->description,
30 NULL);
31 if (IS_ERR(key)) {
32 if (PTR_ERR(key) != -ENOKEY) {
33 _leave(" = %ld", PTR_ERR(key));
34 return key;
35 }
36
37 /* act as anonymous user */
38 _leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
39 return key_get(cell->anonymous_key);
40 } else {
41 /* act as authorised user */
42 _leave(" = {%x} [auth]", key_serial(key));
43 return key;
44 }
45}
46
47/*
48 * dispose of a permits list
49 */
50void afs_zap_permits(struct rcu_head *rcu)
51{
52 struct afs_permits *permits =
53 container_of(rcu, struct afs_permits, rcu);
54 int loop;
55
56 _enter("{%d}", permits->count);
57
58 for (loop = permits->count - 1; loop >= 0; loop--)
59 key_put(permits->permits[loop].key);
60 kfree(permits);
61}
62
63/*
64 * dispose of a permits list in which all the key pointers have been copied
65 */
66static void afs_dispose_of_permits(struct rcu_head *rcu)
67{
68 struct afs_permits *permits =
69 container_of(rcu, struct afs_permits, rcu);
70
71 _enter("{%d}", permits->count);
72
73 kfree(permits);
74}
75
76/*
77 * get the authorising vnode - this is the specified inode itself if it's a
78 * directory or it's the parent directory if the specified inode is a file or
79 * symlink
80 * - the caller must release the ref on the inode
81 */
82static struct afs_vnode *afs_get_auth_inode(struct afs_vnode *vnode,
83 struct key *key)
84{
85 struct afs_vnode *auth_vnode;
86 struct inode *auth_inode;
87
88 _enter("");
89
90 if (S_ISDIR(vnode->vfs_inode.i_mode)) {
91 auth_inode = igrab(&vnode->vfs_inode);
92 ASSERT(auth_inode != NULL);
93 } else {
94 auth_inode = afs_iget(vnode->vfs_inode.i_sb, key,
95 &vnode->status.parent);
96 if (IS_ERR(auth_inode))
97 return ERR_PTR(PTR_ERR(auth_inode));
98 }
99
100 auth_vnode = AFS_FS_I(auth_inode);
101 _leave(" = {%x}", auth_vnode->fid.vnode);
102 return auth_vnode;
103}
104
105/*
106 * clear the permit cache on a directory vnode
107 */
108void afs_clear_permits(struct afs_vnode *vnode)
109{
110 struct afs_permits *permits;
111
112 _enter("{%x}", vnode->fid.vnode);
113
114 mutex_lock(&vnode->permits_lock);
115 permits = vnode->permits;
116 rcu_assign_pointer(vnode->permits, NULL);
117 mutex_unlock(&vnode->permits_lock);
118
119 if (permits)
120 call_rcu(&permits->rcu, afs_zap_permits);
121 _leave("");
122}
123
124/*
125 * add the result obtained for a vnode to its or its parent directory's cache
126 * for the key used to access it
127 */
128void afs_cache_permit(struct afs_vnode *vnode, struct key *key, long acl_order)
129{
130 struct afs_permits *permits, *xpermits;
131 struct afs_permit *permit;
132 struct afs_vnode *auth_vnode;
133 int count, loop;
134
135 _enter("{%x},%x,%lx", vnode->fid.vnode, key_serial(key), acl_order);
136
137 auth_vnode = afs_get_auth_inode(vnode, key);
138 if (IS_ERR(auth_vnode)) {
139 _leave(" [get error %ld]", PTR_ERR(auth_vnode));
140 return;
141 }
142
143 mutex_lock(&auth_vnode->permits_lock);
144
145 /* guard against a rename being detected whilst we waited for the
146 * lock */
147 if (memcmp(&auth_vnode->fid, &vnode->status.parent,
148 sizeof(struct afs_fid)) != 0) {
149 _debug("renamed");
150 goto out_unlock;
151 }
152
153 /* have to be careful as the directory's callback may be broken between
154 * us receiving the status we're trying to cache and us getting the
155 * lock to update the cache for the status */
156 if (auth_vnode->acl_order - acl_order > 0) {
157 _debug("ACL changed?");
158 goto out_unlock;
159 }
160
161 /* always update the anonymous mask */
162 _debug("anon access %x", vnode->status.anon_access);
163 auth_vnode->status.anon_access = vnode->status.anon_access;
164 if (key == vnode->volume->cell->anonymous_key)
165 goto out_unlock;
166
167 xpermits = auth_vnode->permits;
168 count = 0;
169 if (xpermits) {
170 /* see if the permit is already in the list
171 * - if it is then we just amend the list
172 */
173 count = xpermits->count;
174 permit = xpermits->permits;
175 for (loop = count; loop > 0; loop--) {
176 if (permit->key == key) {
177 permit->access_mask =
178 vnode->status.caller_access;
179 goto out_unlock;
180 }
181 permit++;
182 }
183 }
184
185 permits = kmalloc(sizeof(*permits) + sizeof(*permit) * (count + 1),
186 GFP_NOFS);
187 if (!permits)
188 goto out_unlock;
189
190 memcpy(permits->permits, xpermits->permits,
191 count * sizeof(struct afs_permit));
192
193 _debug("key %x access %x",
194 key_serial(key), vnode->status.caller_access);
195 permits->permits[count].access_mask = vnode->status.caller_access;
196 permits->permits[count].key = key_get(key);
197 permits->count = count + 1;
198
199 rcu_assign_pointer(auth_vnode->permits, permits);
200 if (xpermits)
201 call_rcu(&xpermits->rcu, afs_dispose_of_permits);
202
203out_unlock:
204 mutex_unlock(&auth_vnode->permits_lock);
205 iput(&auth_vnode->vfs_inode);
206 _leave("");
207}
208
209/*
210 * check with the fileserver to see if the directory or parent directory is
211 * permitted to be accessed with this authorisation, and if so, what access it
212 * is granted
213 */
214static int afs_check_permit(struct afs_vnode *vnode, struct key *key,
215 afs_access_t *_access)
216{
217 struct afs_permits *permits;
218 struct afs_permit *permit;
219 struct afs_vnode *auth_vnode;
220 bool valid;
221 int loop, ret;
222
223 _enter("");
224
225 auth_vnode = afs_get_auth_inode(vnode, key);
226 if (IS_ERR(auth_vnode)) {
227 *_access = 0;
228 _leave(" = %ld", PTR_ERR(auth_vnode));
229 return PTR_ERR(auth_vnode);
230 }
231
232 ASSERT(S_ISDIR(auth_vnode->vfs_inode.i_mode));
233
234 /* check the permits to see if we've got one yet */
235 if (key == auth_vnode->volume->cell->anonymous_key) {
236 _debug("anon");
237 *_access = auth_vnode->status.anon_access;
238 valid = true;
239 } else {
240 valid = false;
241 rcu_read_lock();
242 permits = rcu_dereference(auth_vnode->permits);
243 if (permits) {
244 permit = permits->permits;
245 for (loop = permits->count; loop > 0; loop--) {
246 if (permit->key == key) {
247 _debug("found in cache");
248 *_access = permit->access_mask;
249 valid = true;
250 break;
251 }
252 permit++;
253 }
254 }
255 rcu_read_unlock();
256 }
257
258 if (!valid) {
259 /* check the status on the file we're actually interested in
260 * (the post-processing will cache the result on auth_vnode) */
261 _debug("no valid permit");
262
263 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
264 ret = afs_vnode_fetch_status(vnode, auth_vnode, key);
265 if (ret < 0) {
266 iput(&auth_vnode->vfs_inode);
267 *_access = 0;
268 _leave(" = %d", ret);
269 return ret;
270 }
271 }
272
273 *_access = vnode->status.caller_access;
274 iput(&auth_vnode->vfs_inode);
275 _leave(" = 0 [access %x]", *_access);
276 return 0;
277}
278
279/*
280 * check the permissions on an AFS file
281 * - AFS ACLs are attached to directories only, and a file is controlled by its
282 * parent directory's ACL
283 */
284int afs_permission(struct inode *inode, int mask, struct nameidata *nd)
285{
286 struct afs_vnode *vnode = AFS_FS_I(inode);
287 afs_access_t access;
288 struct key *key;
289 int ret;
290
291 _enter("{%x:%x},%x,", vnode->fid.vid, vnode->fid.vnode, mask);
292
293 key = afs_request_key(vnode->volume->cell);
294 if (IS_ERR(key)) {
295 _leave(" = %ld [key]", PTR_ERR(key));
296 return PTR_ERR(key);
297 }
298
299 /* check the permits to see if we've got one yet */
300 ret = afs_check_permit(vnode, key, &access);
301 if (ret < 0) {
302 key_put(key);
303 _leave(" = %d [check]", ret);
304 return ret;
305 }
306
307 /* interpret the access mask */
308 _debug("REQ %x ACC %x on %s",
309 mask, access, S_ISDIR(inode->i_mode) ? "dir" : "file");
310
311 if (S_ISDIR(inode->i_mode)) {
312 if (mask & MAY_EXEC) {
313 if (!(access & AFS_ACE_LOOKUP))
314 goto permission_denied;
315 } else if (mask & MAY_READ) {
316 if (!(access & AFS_ACE_READ))
317 goto permission_denied;
318 } else if (mask & MAY_WRITE) {
319 if (!(access & (AFS_ACE_DELETE | /* rmdir, unlink, rename from */
320 AFS_ACE_INSERT | /* create, mkdir, symlink, rename to */
321 AFS_ACE_WRITE))) /* chmod */
322 goto permission_denied;
323 } else {
324 BUG();
325 }
326 } else {
327 if (!(access & AFS_ACE_LOOKUP))
328 goto permission_denied;
329 if (mask & (MAY_EXEC | MAY_READ)) {
330 if (!(access & AFS_ACE_READ))
331 goto permission_denied;
332 } else if (mask & MAY_WRITE) {
333 if (!(access & AFS_ACE_WRITE))
334 goto permission_denied;
335 }
336 }
337
338 key_put(key);
339 return generic_permission(inode, mask, NULL);
340
341permission_denied:
342 key_put(key);
343 _leave(" = -EACCES");
344 return -EACCES;
345}
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 77e68759788f..497350a5463b 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -24,12 +24,6 @@
24 24
25#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ 25#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
26 26
27struct afs_mount_params {
28 int rwpath;
29 struct afs_cell *default_cell;
30 struct afs_volume *volume;
31};
32
33static void afs_i_init_once(void *foo, struct kmem_cache *cachep, 27static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
34 unsigned long flags); 28 unsigned long flags);
35 29
@@ -150,8 +144,8 @@ static int want_no_value(char *const *_value, const char *option)
150 * - this function has been shamelessly adapted from the ext3 fs which 144 * - this function has been shamelessly adapted from the ext3 fs which
151 * shamelessly adapted it from the msdos fs 145 * shamelessly adapted it from the msdos fs
152 */ 146 */
153static int afs_super_parse_options(struct afs_mount_params *params, 147static int afs_parse_options(struct afs_mount_params *params,
154 char *options, const char **devname) 148 char *options, const char **devname)
155{ 149{
156 struct afs_cell *cell; 150 struct afs_cell *cell;
157 char *key, *value; 151 char *key, *value;
@@ -183,8 +177,8 @@ static int afs_super_parse_options(struct afs_mount_params *params,
183 cell = afs_cell_lookup(value, strlen(value)); 177 cell = afs_cell_lookup(value, strlen(value));
184 if (IS_ERR(cell)) 178 if (IS_ERR(cell))
185 return PTR_ERR(cell); 179 return PTR_ERR(cell);
186 afs_put_cell(params->default_cell); 180 afs_put_cell(params->cell);
187 params->default_cell = cell; 181 params->cell = cell;
188 } else { 182 } else {
189 printk("kAFS: Unknown mount option: '%s'\n", key); 183 printk("kAFS: Unknown mount option: '%s'\n", key);
190 ret = -EINVAL; 184 ret = -EINVAL;
@@ -199,6 +193,99 @@ error:
199} 193}
200 194
201/* 195/*
196 * parse a device name to get cell name, volume name, volume type and R/W
197 * selector
198 * - this can be one of the following:
199 * "%[cell:]volume[.]" R/W volume
200 * "#[cell:]volume[.]" R/O or R/W volume (rwpath=0),
201 * or R/W (rwpath=1) volume
202 * "%[cell:]volume.readonly" R/O volume
203 * "#[cell:]volume.readonly" R/O volume
204 * "%[cell:]volume.backup" Backup volume
205 * "#[cell:]volume.backup" Backup volume
206 */
207static int afs_parse_device_name(struct afs_mount_params *params,
208 const char *name)
209{
210 struct afs_cell *cell;
211 const char *cellname, *suffix;
212 int cellnamesz;
213
214 _enter(",%s", name);
215
216 if (!name) {
217 printk(KERN_ERR "kAFS: no volume name specified\n");
218 return -EINVAL;
219 }
220
221 if ((name[0] != '%' && name[0] != '#') || !name[1]) {
222 printk(KERN_ERR "kAFS: unparsable volume name\n");
223 return -EINVAL;
224 }
225
226 /* determine the type of volume we're looking for */
227 params->type = AFSVL_ROVOL;
228 params->force = false;
229 if (params->rwpath || name[0] == '%') {
230 params->type = AFSVL_RWVOL;
231 params->force = true;
232 }
233 name++;
234
235 /* split the cell name out if there is one */
236 params->volname = strchr(name, ':');
237 if (params->volname) {
238 cellname = name;
239 cellnamesz = params->volname - name;
240 params->volname++;
241 } else {
242 params->volname = name;
243 cellname = NULL;
244 cellnamesz = 0;
245 }
246
247 /* the volume type is further affected by a possible suffix */
248 suffix = strrchr(params->volname, '.');
249 if (suffix) {
250 if (strcmp(suffix, ".readonly") == 0) {
251 params->type = AFSVL_ROVOL;
252 params->force = true;
253 } else if (strcmp(suffix, ".backup") == 0) {
254 params->type = AFSVL_BACKVOL;
255 params->force = true;
256 } else if (suffix[1] == 0) {
257 } else {
258 suffix = NULL;
259 }
260 }
261
262 params->volnamesz = suffix ?
263 suffix - params->volname : strlen(params->volname);
264
265 _debug("cell %*.*s [%p]",
266 cellnamesz, cellnamesz, cellname ?: "", params->cell);
267
268 /* lookup the cell record */
269 if (cellname || !params->cell) {
270 cell = afs_cell_lookup(cellname, cellnamesz);
271 if (IS_ERR(cell)) {
272 printk(KERN_ERR "kAFS: unable to lookup cell '%s'\n",
273 cellname ?: "");
274 return PTR_ERR(cell);
275 }
276 afs_put_cell(params->cell);
277 params->cell = cell;
278 }
279
280 _debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
281 params->cell->name, params->cell,
282 params->volnamesz, params->volnamesz, params->volname,
283 suffix ?: "-", params->type, params->force ? " FORCE" : "");
284
285 return 0;
286}
287
288/*
202 * check a superblock to see if it's the one we're looking for 289 * check a superblock to see if it's the one we're looking for
203 */ 290 */
204static int afs_test_super(struct super_block *sb, void *data) 291static int afs_test_super(struct super_block *sb, void *data)
@@ -244,7 +331,7 @@ static int afs_fill_super(struct super_block *sb, void *data)
244 fid.vid = as->volume->vid; 331 fid.vid = as->volume->vid;
245 fid.vnode = 1; 332 fid.vnode = 1;
246 fid.unique = 1; 333 fid.unique = 1;
247 inode = afs_iget(sb, &fid); 334 inode = afs_iget(sb, params->key, &fid);
248 if (IS_ERR(inode)) 335 if (IS_ERR(inode))
249 goto error_inode; 336 goto error_inode;
250 337
@@ -285,31 +372,40 @@ static int afs_get_sb(struct file_system_type *fs_type,
285 struct afs_mount_params params; 372 struct afs_mount_params params;
286 struct super_block *sb; 373 struct super_block *sb;
287 struct afs_volume *vol; 374 struct afs_volume *vol;
375 struct key *key;
288 int ret; 376 int ret;
289 377
290 _enter(",,%s,%p", dev_name, options); 378 _enter(",,%s,%p", dev_name, options);
291 379
292 memset(&params, 0, sizeof(params)); 380 memset(&params, 0, sizeof(params));
293 381
294 /* parse the options */ 382 /* parse the options and device name */
295 if (options) { 383 if (options) {
296 ret = afs_super_parse_options(&params, options, &dev_name); 384 ret = afs_parse_options(&params, options, &dev_name);
297 if (ret < 0) 385 if (ret < 0)
298 goto error; 386 goto error;
299 if (!dev_name) {
300 printk("kAFS: no volume name specified\n");
301 ret = -EINVAL;
302 goto error;
303 }
304 } 387 }
305 388
389
390 ret = afs_parse_device_name(&params, dev_name);
391 if (ret < 0)
392 goto error;
393
394 /* try and do the mount securely */
395 key = afs_request_key(params.cell);
396 if (IS_ERR(key)) {
397 _leave(" = %ld [key]", PTR_ERR(key));
398 ret = PTR_ERR(key);
399 goto error;
400 }
401 params.key = key;
402
306 /* parse the device name */ 403 /* parse the device name */
307 vol = afs_volume_lookup(dev_name, params.default_cell, params.rwpath); 404 vol = afs_volume_lookup(&params);
308 if (IS_ERR(vol)) { 405 if (IS_ERR(vol)) {
309 ret = PTR_ERR(vol); 406 ret = PTR_ERR(vol);
310 goto error; 407 goto error;
311 } 408 }
312
313 params.volume = vol; 409 params.volume = vol;
314 410
315 /* allocate a deviceless superblock */ 411 /* allocate a deviceless superblock */
@@ -337,13 +433,14 @@ static int afs_get_sb(struct file_system_type *fs_type,
337 433
338 simple_set_mnt(mnt, sb); 434 simple_set_mnt(mnt, sb);
339 afs_put_volume(params.volume); 435 afs_put_volume(params.volume);
340 afs_put_cell(params.default_cell); 436 afs_put_cell(params.cell);
341 _leave(" = 0 [%p]", sb); 437 _leave(" = 0 [%p]", sb);
342 return 0; 438 return 0;
343 439
344error: 440error:
345 afs_put_volume(params.volume); 441 afs_put_volume(params.volume);
346 afs_put_cell(params.default_cell); 442 afs_put_cell(params.cell);
443 key_put(params.key);
347 _leave(" = %d", ret); 444 _leave(" = %d", ret);
348 return ret; 445 return ret;
349} 446}
@@ -375,6 +472,7 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
375 memset(vnode, 0, sizeof(*vnode)); 472 memset(vnode, 0, sizeof(*vnode));
376 inode_init_once(&vnode->vfs_inode); 473 inode_init_once(&vnode->vfs_inode);
377 init_waitqueue_head(&vnode->update_waitq); 474 init_waitqueue_head(&vnode->update_waitq);
475 mutex_init(&vnode->permits_lock);
378 spin_lock_init(&vnode->lock); 476 spin_lock_init(&vnode->lock);
379 INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); 477 INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
380 mutex_init(&vnode->cb_broken_lock); 478 mutex_init(&vnode->cb_broken_lock);
diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c
index 0c7eba174836..36c1306e09e0 100644
--- a/fs/afs/vlclient.c
+++ b/fs/afs/vlclient.c
@@ -127,6 +127,7 @@ static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call,
127 * VL.GetEntryByName operation type 127 * VL.GetEntryByName operation type
128 */ 128 */
129static const struct afs_call_type afs_RXVLGetEntryByName = { 129static const struct afs_call_type afs_RXVLGetEntryByName = {
130 .name = "VL.GetEntryByName",
130 .deliver = afs_deliver_vl_get_entry_by_xxx, 131 .deliver = afs_deliver_vl_get_entry_by_xxx,
131 .abort_to_error = afs_vl_abort_to_error, 132 .abort_to_error = afs_vl_abort_to_error,
132 .destructor = afs_flat_call_destructor, 133 .destructor = afs_flat_call_destructor,
@@ -136,6 +137,7 @@ static const struct afs_call_type afs_RXVLGetEntryByName = {
136 * VL.GetEntryById operation type 137 * VL.GetEntryById operation type
137 */ 138 */
138static const struct afs_call_type afs_RXVLGetEntryById = { 139static const struct afs_call_type afs_RXVLGetEntryById = {
140 .name = "VL.GetEntryById",
139 .deliver = afs_deliver_vl_get_entry_by_xxx, 141 .deliver = afs_deliver_vl_get_entry_by_xxx,
140 .abort_to_error = afs_vl_abort_to_error, 142 .abort_to_error = afs_vl_abort_to_error,
141 .destructor = afs_flat_call_destructor, 143 .destructor = afs_flat_call_destructor,
@@ -145,6 +147,7 @@ static const struct afs_call_type afs_RXVLGetEntryById = {
145 * dispatch a get volume entry by name operation 147 * dispatch a get volume entry by name operation
146 */ 148 */
147int afs_vl_get_entry_by_name(struct in_addr *addr, 149int afs_vl_get_entry_by_name(struct in_addr *addr,
150 struct key *key,
148 const char *volname, 151 const char *volname,
149 struct afs_cache_vlocation *entry, 152 struct afs_cache_vlocation *entry,
150 const struct afs_wait_mode *wait_mode) 153 const struct afs_wait_mode *wait_mode)
@@ -163,6 +166,7 @@ int afs_vl_get_entry_by_name(struct in_addr *addr,
163 if (!call) 166 if (!call)
164 return -ENOMEM; 167 return -ENOMEM;
165 168
169 call->key = key;
166 call->reply = entry; 170 call->reply = entry;
167 call->service_id = VL_SERVICE; 171 call->service_id = VL_SERVICE;
168 call->port = htons(AFS_VL_PORT); 172 call->port = htons(AFS_VL_PORT);
@@ -183,6 +187,7 @@ int afs_vl_get_entry_by_name(struct in_addr *addr,
183 * dispatch a get volume entry by ID operation 187 * dispatch a get volume entry by ID operation
184 */ 188 */
185int afs_vl_get_entry_by_id(struct in_addr *addr, 189int afs_vl_get_entry_by_id(struct in_addr *addr,
190 struct key *key,
186 afs_volid_t volid, 191 afs_volid_t volid,
187 afs_voltype_t voltype, 192 afs_voltype_t voltype,
188 struct afs_cache_vlocation *entry, 193 struct afs_cache_vlocation *entry,
@@ -197,6 +202,7 @@ int afs_vl_get_entry_by_id(struct in_addr *addr,
197 if (!call) 202 if (!call)
198 return -ENOMEM; 203 return -ENOMEM;
199 204
205 call->key = key;
200 call->reply = entry; 206 call->reply = entry;
201 call->service_id = VL_SERVICE; 207 call->service_id = VL_SERVICE;
202 call->port = htons(AFS_VL_PORT); 208 call->port = htons(AFS_VL_PORT);
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index 60cb2f408c75..7d9815e9ae0f 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -33,6 +33,7 @@ static struct workqueue_struct *afs_vlocation_update_worker;
33 * about the volume in question 33 * about the volume in question
34 */ 34 */
35static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl, 35static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
36 struct key *key,
36 struct afs_cache_vlocation *vldb) 37 struct afs_cache_vlocation *vldb)
37{ 38{
38 struct afs_cell *cell = vl->cell; 39 struct afs_cell *cell = vl->cell;
@@ -49,7 +50,7 @@ static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
49 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr); 50 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
50 51
51 /* attempt to access the VL server */ 52 /* attempt to access the VL server */
52 ret = afs_vl_get_entry_by_name(&addr, vl->vldb.name, vldb, 53 ret = afs_vl_get_entry_by_name(&addr, key, vl->vldb.name, vldb,
53 &afs_sync_call); 54 &afs_sync_call);
54 switch (ret) { 55 switch (ret) {
55 case 0: 56 case 0:
@@ -86,6 +87,7 @@ out:
86 * about the volume in question 87 * about the volume in question
87 */ 88 */
88static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl, 89static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
90 struct key *key,
89 afs_volid_t volid, 91 afs_volid_t volid,
90 afs_voltype_t voltype, 92 afs_voltype_t voltype,
91 struct afs_cache_vlocation *vldb) 93 struct afs_cache_vlocation *vldb)
@@ -104,7 +106,7 @@ static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
104 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr); 106 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
105 107
106 /* attempt to access the VL server */ 108 /* attempt to access the VL server */
107 ret = afs_vl_get_entry_by_id(&addr, volid, voltype, vldb, 109 ret = afs_vl_get_entry_by_id(&addr, key, volid, voltype, vldb,
108 &afs_sync_call); 110 &afs_sync_call);
109 switch (ret) { 111 switch (ret) {
110 case 0: 112 case 0:
@@ -188,6 +190,7 @@ static struct afs_vlocation *afs_vlocation_alloc(struct afs_cell *cell,
188 * update record if we found it in the cache 190 * update record if we found it in the cache
189 */ 191 */
190static int afs_vlocation_update_record(struct afs_vlocation *vl, 192static int afs_vlocation_update_record(struct afs_vlocation *vl,
193 struct key *key,
191 struct afs_cache_vlocation *vldb) 194 struct afs_cache_vlocation *vldb)
192{ 195{
193 afs_voltype_t voltype; 196 afs_voltype_t voltype;
@@ -228,7 +231,7 @@ static int afs_vlocation_update_record(struct afs_vlocation *vl,
228 /* contact the server to make sure the volume is still available 231 /* contact the server to make sure the volume is still available
229 * - TODO: need to handle disconnected operation here 232 * - TODO: need to handle disconnected operation here
230 */ 233 */
231 ret = afs_vlocation_access_vl_by_id(vl, vid, voltype, vldb); 234 ret = afs_vlocation_access_vl_by_id(vl, key, vid, voltype, vldb);
232 switch (ret) { 235 switch (ret) {
233 /* net error */ 236 /* net error */
234 default: 237 default:
@@ -287,7 +290,8 @@ static void afs_vlocation_apply_update(struct afs_vlocation *vl,
287 * fill in a volume location record, consulting the cache and the VL server 290 * fill in a volume location record, consulting the cache and the VL server
288 * both 291 * both
289 */ 292 */
290static int afs_vlocation_fill_in_record(struct afs_vlocation *vl) 293static int afs_vlocation_fill_in_record(struct afs_vlocation *vl,
294 struct key *key)
291{ 295{
292 struct afs_cache_vlocation vldb; 296 struct afs_cache_vlocation vldb;
293 int ret; 297 int ret;
@@ -310,11 +314,11 @@ static int afs_vlocation_fill_in_record(struct afs_vlocation *vl)
310 /* try to update a known volume in the cell VL databases by 314 /* try to update a known volume in the cell VL databases by
311 * ID as the name may have changed */ 315 * ID as the name may have changed */
312 _debug("found in cache"); 316 _debug("found in cache");
313 ret = afs_vlocation_update_record(vl, &vldb); 317 ret = afs_vlocation_update_record(vl, key, &vldb);
314 } else { 318 } else {
315 /* try to look up an unknown volume in the cell VL databases by 319 /* try to look up an unknown volume in the cell VL databases by
316 * name */ 320 * name */
317 ret = afs_vlocation_access_vl_by_name(vl, &vldb); 321 ret = afs_vlocation_access_vl_by_name(vl, key, &vldb);
318 if (ret < 0) { 322 if (ret < 0) {
319 printk("kAFS: failed to locate '%s' in cell '%s'\n", 323 printk("kAFS: failed to locate '%s' in cell '%s'\n",
320 vl->vldb.name, vl->cell->name); 324 vl->vldb.name, vl->cell->name);
@@ -366,14 +370,16 @@ void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
366 * - insert/update in the local cache if did get a VL response 370 * - insert/update in the local cache if did get a VL response
367 */ 371 */
368struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell, 372struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
373 struct key *key,
369 const char *name, 374 const char *name,
370 size_t namesz) 375 size_t namesz)
371{ 376{
372 struct afs_vlocation *vl; 377 struct afs_vlocation *vl;
373 int ret; 378 int ret;
374 379
375 _enter("{%s},%*.*s,%zu", 380 _enter("{%s},{%x},%*.*s,%zu",
376 cell->name, (int) namesz, (int) namesz, name, namesz); 381 cell->name, key_serial(key),
382 (int) namesz, (int) namesz, name, namesz);
377 383
378 if (namesz > sizeof(vl->vldb.name)) { 384 if (namesz > sizeof(vl->vldb.name)) {
379 _leave(" = -ENAMETOOLONG"); 385 _leave(" = -ENAMETOOLONG");
@@ -405,7 +411,7 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
405 up_write(&cell->vl_sem); 411 up_write(&cell->vl_sem);
406 412
407fill_in_record: 413fill_in_record:
408 ret = afs_vlocation_fill_in_record(vl); 414 ret = afs_vlocation_fill_in_record(vl, key);
409 if (ret < 0) 415 if (ret < 0)
410 goto error_abandon; 416 goto error_abandon;
411 vl->state = AFS_VL_VALID; 417 vl->state = AFS_VL_VALID;
@@ -656,7 +662,7 @@ static void afs_vlocation_updater(struct work_struct *work)
656 vl->upd_rej_cnt = 0; 662 vl->upd_rej_cnt = 0;
657 vl->upd_busy_cnt = 0; 663 vl->upd_busy_cnt = 0;
658 664
659 ret = afs_vlocation_update_record(vl, &vldb); 665 ret = afs_vlocation_update_record(vl, NULL, &vldb);
660 switch (ret) { 666 switch (ret) {
661 case 0: 667 case 0:
662 afs_vlocation_apply_update(vl, &vldb); 668 afs_vlocation_apply_update(vl, &vldb);
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c
index d2ca1398474f..160097619ec7 100644
--- a/fs/afs/vnode.c
+++ b/fs/afs/vnode.c
@@ -238,9 +238,11 @@ static void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
238 * - there are any outstanding ops that will fetch the status 238 * - there are any outstanding ops that will fetch the status
239 * - TODO implement local caching 239 * - TODO implement local caching
240 */ 240 */
241int afs_vnode_fetch_status(struct afs_vnode *vnode) 241int afs_vnode_fetch_status(struct afs_vnode *vnode,
242 struct afs_vnode *auth_vnode, struct key *key)
242{ 243{
243 struct afs_server *server; 244 struct afs_server *server;
245 unsigned long acl_order;
244 int ret; 246 int ret;
245 247
246 DECLARE_WAITQUEUE(myself, current); 248 DECLARE_WAITQUEUE(myself, current);
@@ -260,6 +262,10 @@ int afs_vnode_fetch_status(struct afs_vnode *vnode)
260 return -ENOENT; 262 return -ENOENT;
261 } 263 }
262 264
265 acl_order = 0;
266 if (auth_vnode)
267 acl_order = auth_vnode->acl_order;
268
263 spin_lock(&vnode->lock); 269 spin_lock(&vnode->lock);
264 270
265 if (!test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags) && 271 if (!test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags) &&
@@ -324,12 +330,14 @@ get_anyway:
324 _debug("USING SERVER: %p{%08x}", 330 _debug("USING SERVER: %p{%08x}",
325 server, ntohl(server->addr.s_addr)); 331 server, ntohl(server->addr.s_addr));
326 332
327 ret = afs_fs_fetch_file_status(server, vnode, NULL, 333 ret = afs_fs_fetch_file_status(server, key, vnode, NULL,
328 &afs_sync_call); 334 &afs_sync_call);
329 335
330 } while (!afs_volume_release_fileserver(vnode, server, ret)); 336 } while (!afs_volume_release_fileserver(vnode, server, ret));
331 337
332 /* adjust the flags */ 338 /* adjust the flags */
339 if (ret == 0 && auth_vnode)
340 afs_cache_permit(vnode, key, acl_order);
333 afs_vnode_finalise_status_update(vnode, server, ret); 341 afs_vnode_finalise_status_update(vnode, server, ret);
334 342
335 _leave(" = %d", ret); 343 _leave(" = %d", ret);
@@ -340,17 +348,18 @@ get_anyway:
340 * fetch file data from the volume 348 * fetch file data from the volume
341 * - TODO implement caching and server failover 349 * - TODO implement caching and server failover
342 */ 350 */
343int afs_vnode_fetch_data(struct afs_vnode *vnode, off_t offset, size_t length, 351int afs_vnode_fetch_data(struct afs_vnode *vnode, struct key *key,
344 struct page *page) 352 off_t offset, size_t length, struct page *page)
345{ 353{
346 struct afs_server *server; 354 struct afs_server *server;
347 int ret; 355 int ret;
348 356
349 _enter("%s,{%u,%u,%u}", 357 _enter("%s{%u,%u,%u},%x,,,",
350 vnode->volume->vlocation->vldb.name, 358 vnode->volume->vlocation->vldb.name,
351 vnode->fid.vid, 359 vnode->fid.vid,
352 vnode->fid.vnode, 360 vnode->fid.vnode,
353 vnode->fid.unique); 361 vnode->fid.unique,
362 key_serial(key));
354 363
355 /* this op will fetch the status */ 364 /* this op will fetch the status */
356 spin_lock(&vnode->lock); 365 spin_lock(&vnode->lock);
@@ -367,8 +376,8 @@ int afs_vnode_fetch_data(struct afs_vnode *vnode, off_t offset, size_t length,
367 376
368 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); 377 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
369 378
370 ret = afs_fs_fetch_data(server, vnode, offset, length, page, 379 ret = afs_fs_fetch_data(server, key, vnode, offset, length,
371 NULL, &afs_sync_call); 380 page, NULL, &afs_sync_call);
372 381
373 } while (!afs_volume_release_fileserver(vnode, server, ret)); 382 } while (!afs_volume_release_fileserver(vnode, server, ret));
374 383
diff --git a/fs/afs/volume.c b/fs/afs/volume.c
index 45491cfd4f4f..15e13678c216 100644
--- a/fs/afs/volume.c
+++ b/fs/afs/volume.c
@@ -41,83 +41,20 @@ static const char *afs_voltypes[] = { "R/W", "R/O", "BAK" };
41 * - Rule 3: If parent volume is R/W, then only mount R/W volume unless 41 * - Rule 3: If parent volume is R/W, then only mount R/W volume unless
42 * explicitly told otherwise 42 * explicitly told otherwise
43 */ 43 */
44struct afs_volume *afs_volume_lookup(const char *name, struct afs_cell *cell, 44struct afs_volume *afs_volume_lookup(struct afs_mount_params *params)
45 int rwpath)
46{ 45{
47 struct afs_vlocation *vlocation = NULL; 46 struct afs_vlocation *vlocation = NULL;
48 struct afs_volume *volume = NULL; 47 struct afs_volume *volume = NULL;
49 struct afs_server *server = NULL; 48 struct afs_server *server = NULL;
50 afs_voltype_t type;
51 const char *cellname, *volname, *suffix;
52 char srvtmask; 49 char srvtmask;
53 int force, ret, loop, cellnamesz, volnamesz; 50 int ret, loop;
54 51
55 _enter("%s,,%d,", name, rwpath); 52 _enter("{%*.*s,%d}",
56 53 params->volnamesz, params->volnamesz, params->volname, params->rwpath);
57 if (!name || (name[0] != '%' && name[0] != '#') || !name[1]) {
58 printk("kAFS: unparsable volume name\n");
59 return ERR_PTR(-EINVAL);
60 }
61
62 /* determine the type of volume we're looking for */
63 force = 0;
64 type = AFSVL_ROVOL;
65
66 if (rwpath || name[0] == '%') {
67 type = AFSVL_RWVOL;
68 force = 1;
69 }
70
71 suffix = strrchr(name, '.');
72 if (suffix) {
73 if (strcmp(suffix, ".readonly") == 0) {
74 type = AFSVL_ROVOL;
75 force = 1;
76 } else if (strcmp(suffix, ".backup") == 0) {
77 type = AFSVL_BACKVOL;
78 force = 1;
79 } else if (suffix[1] == 0) {
80 } else {
81 suffix = NULL;
82 }
83 }
84
85 /* split the cell and volume names */
86 name++;
87 volname = strchr(name, ':');
88 if (volname) {
89 cellname = name;
90 cellnamesz = volname - name;
91 volname++;
92 } else {
93 volname = name;
94 cellname = NULL;
95 cellnamesz = 0;
96 }
97
98 volnamesz = suffix ? suffix - volname : strlen(volname);
99
100 _debug("CELL:%*.*s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
101 cellnamesz, cellnamesz, cellname ?: "", cell,
102 volnamesz, volnamesz, volname, suffix ?: "-",
103 type,
104 force ? " FORCE" : "");
105
106 /* lookup the cell record */
107 if (cellname || !cell) {
108 cell = afs_cell_lookup(cellname, cellnamesz);
109 if (IS_ERR(cell)) {
110 ret = PTR_ERR(cell);
111 printk("kAFS: unable to lookup cell '%s'\n",
112 cellname ?: "");
113 goto error;
114 }
115 } else {
116 afs_get_cell(cell);
117 }
118 54
119 /* lookup the volume location record */ 55 /* lookup the volume location record */
120 vlocation = afs_vlocation_lookup(cell, volname, volnamesz); 56 vlocation = afs_vlocation_lookup(params->cell, params->key,
57 params->volname, params->volnamesz);
121 if (IS_ERR(vlocation)) { 58 if (IS_ERR(vlocation)) {
122 ret = PTR_ERR(vlocation); 59 ret = PTR_ERR(vlocation);
123 vlocation = NULL; 60 vlocation = NULL;
@@ -126,30 +63,30 @@ struct afs_volume *afs_volume_lookup(const char *name, struct afs_cell *cell,
126 63
127 /* make the final decision on the type we want */ 64 /* make the final decision on the type we want */
128 ret = -ENOMEDIUM; 65 ret = -ENOMEDIUM;
129 if (force && !(vlocation->vldb.vidmask & (1 << type))) 66 if (params->force && !(vlocation->vldb.vidmask & (1 << params->type)))
130 goto error; 67 goto error;
131 68
132 srvtmask = 0; 69 srvtmask = 0;
133 for (loop = 0; loop < vlocation->vldb.nservers; loop++) 70 for (loop = 0; loop < vlocation->vldb.nservers; loop++)
134 srvtmask |= vlocation->vldb.srvtmask[loop]; 71 srvtmask |= vlocation->vldb.srvtmask[loop];
135 72
136 if (force) { 73 if (params->force) {
137 if (!(srvtmask & (1 << type))) 74 if (!(srvtmask & (1 << params->type)))
138 goto error; 75 goto error;
139 } else if (srvtmask & AFS_VOL_VTM_RO) { 76 } else if (srvtmask & AFS_VOL_VTM_RO) {
140 type = AFSVL_ROVOL; 77 params->type = AFSVL_ROVOL;
141 } else if (srvtmask & AFS_VOL_VTM_RW) { 78 } else if (srvtmask & AFS_VOL_VTM_RW) {
142 type = AFSVL_RWVOL; 79 params->type = AFSVL_RWVOL;
143 } else { 80 } else {
144 goto error; 81 goto error;
145 } 82 }
146 83
147 down_write(&cell->vl_sem); 84 down_write(&params->cell->vl_sem);
148 85
149 /* is the volume already active? */ 86 /* is the volume already active? */
150 if (vlocation->vols[type]) { 87 if (vlocation->vols[params->type]) {
151 /* yes - re-use it */ 88 /* yes - re-use it */
152 volume = vlocation->vols[type]; 89 volume = vlocation->vols[params->type];
153 afs_get_volume(volume); 90 afs_get_volume(volume);
154 goto success; 91 goto success;
155 } 92 }
@@ -163,10 +100,10 @@ struct afs_volume *afs_volume_lookup(const char *name, struct afs_cell *cell,
163 goto error_up; 100 goto error_up;
164 101
165 atomic_set(&volume->usage, 1); 102 atomic_set(&volume->usage, 1);
166 volume->type = type; 103 volume->type = params->type;
167 volume->type_force = force; 104 volume->type_force = params->force;
168 volume->cell = cell; 105 volume->cell = params->cell;
169 volume->vid = vlocation->vldb.vid[type]; 106 volume->vid = vlocation->vldb.vid[params->type];
170 107
171 init_rwsem(&volume->server_sem); 108 init_rwsem(&volume->server_sem);
172 109
@@ -196,28 +133,26 @@ struct afs_volume *afs_volume_lookup(const char *name, struct afs_cell *cell,
196 afs_get_vlocation(vlocation); 133 afs_get_vlocation(vlocation);
197 volume->vlocation = vlocation; 134 volume->vlocation = vlocation;
198 135
199 vlocation->vols[type] = volume; 136 vlocation->vols[volume->type] = volume;
200 137
201success: 138success:
202 _debug("kAFS selected %s volume %08x", 139 _debug("kAFS selected %s volume %08x",
203 afs_voltypes[volume->type], volume->vid); 140 afs_voltypes[volume->type], volume->vid);
204 up_write(&cell->vl_sem); 141 up_write(&params->cell->vl_sem);
205 afs_put_vlocation(vlocation); 142 afs_put_vlocation(vlocation);
206 afs_put_cell(cell);
207 _leave(" = %p", volume); 143 _leave(" = %p", volume);
208 return volume; 144 return volume;
209 145
210 /* clean up */ 146 /* clean up */
211error_up: 147error_up:
212 up_write(&cell->vl_sem); 148 up_write(&params->cell->vl_sem);
213error: 149error:
214 afs_put_vlocation(vlocation); 150 afs_put_vlocation(vlocation);
215 afs_put_cell(cell);
216 _leave(" = %d", ret); 151 _leave(" = %d", ret);
217 return ERR_PTR(ret); 152 return ERR_PTR(ret);
218 153
219error_discard: 154error_discard:
220 up_write(&cell->vl_sem); 155 up_write(&params->cell->vl_sem);
221 156
222 for (loop = volume->nservers - 1; loop >= 0; loop--) 157 for (loop = volume->nservers - 1; loop >= 0; loop--)
223 afs_put_server(volume->servers[loop]); 158 afs_put_server(volume->servers[loop]);