Skip to content

Commit 00d3b7a

Browse files
dhowellsdavem330
authored andcommitted
[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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 436058a commit 00d3b7a

File tree

18 files changed

+945
-238
lines changed

18 files changed

+945
-238
lines changed

fs/afs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ kafs-objs := \
1515
mntpt.o \
1616
proc.o \
1717
rxrpc.o \
18+
security.o \
1819
server.o \
1920
super.o \
2021
vlclient.o \

fs/afs/afs.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
#include <linux/in.h>
1616

17+
#define AFS_MAXCELLNAME 64 /* maximum length of a cell name */
18+
#define AFS_MAXVOLNAME 64 /* maximum length of a volume name */
19+
1720
typedef unsigned afs_volid_t;
1821
typedef unsigned afs_vnodeid_t;
1922
typedef unsigned long long afs_dataversion_t;
@@ -74,6 +77,26 @@ struct afs_volume_info {
7477
} servers[8];
7578
};
7679

80+
/*
81+
* AFS security ACE access mask
82+
*/
83+
typedef 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+
77100
/*
78101
* AFS file status information
79102
*/
@@ -87,8 +110,8 @@ struct afs_file_status {
87110
afs_dataversion_t data_version; /* current data version */
88111
unsigned author; /* author ID */
89112
unsigned owner; /* owner ID */
90-
unsigned caller_access; /* access rights for authenticated caller */
91-
unsigned anon_access; /* access rights for unauthenticated caller */
113+
afs_access_t caller_access; /* access rights for authenticated caller */
114+
afs_access_t anon_access; /* access rights for unauthenticated caller */
92115
umode_t mode; /* UNIX mode */
93116
struct afs_fid parent; /* parent file ID */
94117
time_t mtime_client; /* last time client changed data */

fs/afs/callback.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ void afs_broken_callback_work(struct work_struct *work)
7272
return; /* someone else is dealing with it */
7373

7474
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)
7679
goto out;
7780

7881
if (test_bit(AFS_VNODE_DELETED, &vnode->flags))

fs/afs/cell.c

Lines changed: 77 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
#include <linux/module.h>
1313
#include <linux/slab.h>
14+
#include <linux/key.h>
15+
#include <linux/ctype.h>
16+
#include <keys/rxrpc-type.h>
1417
#include "internal.h"
1518

1619
DECLARE_RWSEM(afs_proc_cells_sem);
@@ -23,45 +26,43 @@ static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq);
2326
static struct afs_cell *afs_cell_root;
2427

2528
/*
26-
* create a cell record
27-
* - "name" is the name of the cell
28-
* - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format
29+
* allocate a cell record and fill in its name, VL server address list and
30+
* allocate an anonymous key
2931
*/
30-
struct afs_cell *afs_cell_create(const char *name, char *vllist)
32+
static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
3133
{
3234
struct afs_cell *cell;
33-
char *next;
35+
size_t namelen;
36+
char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
3437
int ret;
3538

3639
_enter("%s,%s", name, vllist);
3740

3841
BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */
3942

43+
namelen = strlen(name);
44+
if (namelen > AFS_MAXCELLNAME)
45+
return ERR_PTR(-ENAMETOOLONG);
46+
4047
/* 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);
4249
if (!cell) {
4350
_leave(" = -ENOMEM");
4451
return ERR_PTR(-ENOMEM);
4552
}
4653

47-
down_write(&afs_cells_sem);
54+
memcpy(cell->name, name, namelen);
55+
cell->name[namelen] = 0;
4856

49-
memset(cell, 0, sizeof(struct afs_cell));
5057
atomic_set(&cell->usage, 1);
51-
5258
INIT_LIST_HEAD(&cell->link);
53-
5459
rwlock_init(&cell->servers_lock);
5560
INIT_LIST_HEAD(&cell->servers);
56-
5761
init_rwsem(&cell->vl_sem);
5862
INIT_LIST_HEAD(&cell->vl_list);
5963
spin_lock_init(&cell->vl_lock);
6064

61-
strcpy(cell->name, name);
62-
6365
/* fill in the VL server list from the rest of the string */
64-
ret = -EINVAL;
6566
do {
6667
unsigned a, b, c, d;
6768

@@ -70,18 +71,73 @@ struct afs_cell *afs_cell_create(const char *name, char *vllist)
7071
*next++ = 0;
7172

7273
if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
73-
goto badaddr;
74+
goto bad_address;
7475

7576
if (a > 255 || b > 255 || c > 255 || d > 255)
76-
goto badaddr;
77+
goto bad_address;
7778

7879
cell->vl_addrs[cell->vl_naddrs++].s_addr =
7980
htonl((a << 24) | (b << 16) | (c << 8) | d);
8081

81-
if (cell->vl_naddrs >= AFS_CELL_MAX_ADDRS)
82-
break;
82+
} while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next));
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+
112+
bad_address:
113+
printk(KERN_ERR "kAFS: bad VL server IP address\n");
114+
ret = -EINVAL;
115+
error:
116+
key_put(cell->anonymous_key);
117+
kfree(cell);
118+
_leave(" = %d", ret);
119+
return ERR_PTR(ret);
120+
}
83121

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+
*/
127+
struct 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);
85141

86142
/* add a proc directory for this cell */
87143
ret = afs_proc_cell_setup(cell);
@@ -109,10 +165,9 @@ struct afs_cell *afs_cell_create(const char *name, char *vllist)
109165
_leave(" = %p", cell);
110166
return cell;
111167

112-
badaddr:
113-
printk(KERN_ERR "kAFS: bad VL server IP address\n");
114168
error:
115169
up_write(&afs_cells_sem);
170+
key_put(cell->anonymous_key);
116171
kfree(cell);
117172
_leave(" = %d", ret);
118173
return ERR_PTR(ret);
@@ -301,6 +356,7 @@ static void afs_cell_destroy(struct afs_cell *cell)
301356
cachefs_relinquish_cookie(cell->cache, 0);
302357
#endif
303358

359+
key_put(cell->anonymous_key);
304360
kfree(cell);
305361

306362
_leave(" [destroyed]");

fs/afs/cmservice.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ static void afs_cm_destructor(struct afs_call *);
2828
* CB.CallBack operation type
2929
*/
3030
static const struct afs_call_type afs_SRXCBCallBack = {
31+
.name = "CB.CallBack",
3132
.deliver = afs_deliver_cb_callback,
3233
.abort_to_error = afs_abort_to_error,
3334
.destructor = afs_cm_destructor,
@@ -37,6 +38,7 @@ static const struct afs_call_type afs_SRXCBCallBack = {
3738
* CB.InitCallBackState operation type
3839
*/
3940
static const struct afs_call_type afs_SRXCBInitCallBackState = {
41+
.name = "CB.InitCallBackState",
4042
.deliver = afs_deliver_cb_init_call_back_state,
4143
.abort_to_error = afs_abort_to_error,
4244
.destructor = afs_cm_destructor,
@@ -46,6 +48,7 @@ static const struct afs_call_type afs_SRXCBInitCallBackState = {
4648
* CB.Probe operation type
4749
*/
4850
static const struct afs_call_type afs_SRXCBProbe = {
51+
.name = "CB.Probe",
4952
.deliver = afs_deliver_cb_probe,
5053
.abort_to_error = afs_abort_to_error,
5154
.destructor = afs_cm_destructor,

0 commit comments

Comments
 (0)