aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/Kconfig13
-rw-r--r--fs/9p/Makefile4
-rw-r--r--fs/9p/vfs_addr.c5
-rw-r--r--fs/9p/vfs_dir.c72
-rw-r--r--fs/9p/vfs_inode.c2
-rw-r--r--fs/9p/xattr.c4
-rw-r--r--fs/9p/xattr.h2
-rw-r--r--fs/9p/xattr_security.c80
-rw-r--r--fs/9p/xattr_trusted.c80
9 files changed, 213 insertions, 49 deletions
diff --git a/fs/9p/Kconfig b/fs/9p/Kconfig
index 55abfd62654a..6489e1fc1afd 100644
--- a/fs/9p/Kconfig
+++ b/fs/9p/Kconfig
@@ -31,3 +31,16 @@ config 9P_FS_POSIX_ACL
31 If you don't know what Access Control Lists are, say N 31 If you don't know what Access Control Lists are, say N
32 32
33endif 33endif
34
35
36config 9P_FS_SECURITY
37 bool "9P Security Labels"
38 depends on 9P_FS
39 help
40 Security labels support alternative access control models
41 implemented by security modules like SELinux. This option
42 enables an extended attribute handler for file security
43 labels in the 9P filesystem.
44
45 If you are not using a security module that requires using
46 extended attributes for file security labels, say N.
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index ab8c12780634..ff7be98f84f2 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -11,7 +11,9 @@ obj-$(CONFIG_9P_FS) := 9p.o
11 v9fs.o \ 11 v9fs.o \
12 fid.o \ 12 fid.o \
13 xattr.o \ 13 xattr.o \
14 xattr_user.o 14 xattr_user.o \
15 xattr_trusted.o
15 16
169p-$(CONFIG_9P_FSCACHE) += cache.o 179p-$(CONFIG_9P_FSCACHE) += cache.o
179p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o 189p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o
199p-$(CONFIG_9P_FS_SECURITY) += xattr_security.o
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 055562c580b4..9ff073f4090a 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -148,13 +148,14 @@ static int v9fs_release_page(struct page *page, gfp_t gfp)
148 * @offset: offset in the page 148 * @offset: offset in the page
149 */ 149 */
150 150
151static void v9fs_invalidate_page(struct page *page, unsigned long offset) 151static void v9fs_invalidate_page(struct page *page, unsigned int offset,
152 unsigned int length)
152{ 153{
153 /* 154 /*
154 * If called with zero offset, we should release 155 * If called with zero offset, we should release
155 * the private state assocated with the page 156 * the private state assocated with the page
156 */ 157 */
157 if (offset == 0) 158 if (offset == 0 && length == PAGE_CACHE_SIZE)
158 v9fs_fscache_invalidate_page(page); 159 v9fs_fscache_invalidate_page(page);
159} 160}
160 161
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index be1e34adc3c6..4d0c2e0be7e5 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -101,16 +101,15 @@ static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen)
101} 101}
102 102
103/** 103/**
104 * v9fs_dir_readdir - read a directory 104 * v9fs_dir_readdir - iterate through a directory
105 * @filp: opened file structure 105 * @file: opened file structure
106 * @dirent: directory structure ??? 106 * @ctx: actor we feed the entries to
107 * @filldir: function to populate directory structure ???
108 * 107 *
109 */ 108 */
110 109
111static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) 110static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
112{ 111{
113 int over; 112 bool over;
114 struct p9_wstat st; 113 struct p9_wstat st;
115 int err = 0; 114 int err = 0;
116 struct p9_fid *fid; 115 struct p9_fid *fid;
@@ -118,19 +117,19 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
118 int reclen = 0; 117 int reclen = 0;
119 struct p9_rdir *rdir; 118 struct p9_rdir *rdir;
120 119
121 p9_debug(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); 120 p9_debug(P9_DEBUG_VFS, "name %s\n", file->f_path.dentry->d_name.name);
122 fid = filp->private_data; 121 fid = file->private_data;
123 122
124 buflen = fid->clnt->msize - P9_IOHDRSZ; 123 buflen = fid->clnt->msize - P9_IOHDRSZ;
125 124
126 rdir = v9fs_alloc_rdir_buf(filp, buflen); 125 rdir = v9fs_alloc_rdir_buf(file, buflen);
127 if (!rdir) 126 if (!rdir)
128 return -ENOMEM; 127 return -ENOMEM;
129 128
130 while (1) { 129 while (1) {
131 if (rdir->tail == rdir->head) { 130 if (rdir->tail == rdir->head) {
132 err = v9fs_file_readn(filp, rdir->buf, NULL, 131 err = v9fs_file_readn(file, rdir->buf, NULL,
133 buflen, filp->f_pos); 132 buflen, ctx->pos);
134 if (err <= 0) 133 if (err <= 0)
135 return err; 134 return err;
136 135
@@ -148,51 +147,45 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
148 } 147 }
149 reclen = st.size+2; 148 reclen = st.size+2;
150 149
151 over = filldir(dirent, st.name, strlen(st.name), 150 over = !dir_emit(ctx, st.name, strlen(st.name),
152 filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st)); 151 v9fs_qid2ino(&st.qid), dt_type(&st));
153
154 p9stat_free(&st); 152 p9stat_free(&st);
155
156 if (over) 153 if (over)
157 return 0; 154 return 0;
158 155
159 rdir->head += reclen; 156 rdir->head += reclen;
160 filp->f_pos += reclen; 157 ctx->pos += reclen;
161 } 158 }
162 } 159 }
163} 160}
164 161
165/** 162/**
166 * v9fs_dir_readdir_dotl - read a directory 163 * v9fs_dir_readdir_dotl - iterate through a directory
167 * @filp: opened file structure 164 * @file: opened file structure
168 * @dirent: buffer to fill dirent structures 165 * @ctx: actor we feed the entries to
169 * @filldir: function to populate dirent structures
170 * 166 *
171 */ 167 */
172static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent, 168static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
173 filldir_t filldir)
174{ 169{
175 int over;
176 int err = 0; 170 int err = 0;
177 struct p9_fid *fid; 171 struct p9_fid *fid;
178 int buflen; 172 int buflen;
179 struct p9_rdir *rdir; 173 struct p9_rdir *rdir;
180 struct p9_dirent curdirent; 174 struct p9_dirent curdirent;
181 u64 oldoffset = 0;
182 175
183 p9_debug(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); 176 p9_debug(P9_DEBUG_VFS, "name %s\n", file->f_path.dentry->d_name.name);
184 fid = filp->private_data; 177 fid = file->private_data;
185 178
186 buflen = fid->clnt->msize - P9_READDIRHDRSZ; 179 buflen = fid->clnt->msize - P9_READDIRHDRSZ;
187 180
188 rdir = v9fs_alloc_rdir_buf(filp, buflen); 181 rdir = v9fs_alloc_rdir_buf(file, buflen);
189 if (!rdir) 182 if (!rdir)
190 return -ENOMEM; 183 return -ENOMEM;
191 184
192 while (1) { 185 while (1) {
193 if (rdir->tail == rdir->head) { 186 if (rdir->tail == rdir->head) {
194 err = p9_client_readdir(fid, rdir->buf, buflen, 187 err = p9_client_readdir(fid, rdir->buf, buflen,
195 filp->f_pos); 188 ctx->pos);
196 if (err <= 0) 189 if (err <= 0)
197 return err; 190 return err;
198 191
@@ -210,22 +203,13 @@ static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent,
210 return -EIO; 203 return -EIO;
211 } 204 }
212 205
213 /* d_off in dirent structure tracks the offset into 206 if (!dir_emit(ctx, curdirent.d_name,
214 * the next dirent in the dir. However, filldir() 207 strlen(curdirent.d_name),
215 * expects offset into the current dirent. Hence 208 v9fs_qid2ino(&curdirent.qid),
216 * while calling filldir send the offset from the 209 curdirent.d_type))
217 * previous dirent structure.
218 */
219 over = filldir(dirent, curdirent.d_name,
220 strlen(curdirent.d_name),
221 oldoffset, v9fs_qid2ino(&curdirent.qid),
222 curdirent.d_type);
223 oldoffset = curdirent.d_off;
224
225 if (over)
226 return 0; 210 return 0;
227 211
228 filp->f_pos = curdirent.d_off; 212 ctx->pos = curdirent.d_off;
229 rdir->head += err; 213 rdir->head += err;
230 } 214 }
231 } 215 }
@@ -254,7 +238,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
254const struct file_operations v9fs_dir_operations = { 238const struct file_operations v9fs_dir_operations = {
255 .read = generic_read_dir, 239 .read = generic_read_dir,
256 .llseek = generic_file_llseek, 240 .llseek = generic_file_llseek,
257 .readdir = v9fs_dir_readdir, 241 .iterate = v9fs_dir_readdir,
258 .open = v9fs_file_open, 242 .open = v9fs_file_open,
259 .release = v9fs_dir_release, 243 .release = v9fs_dir_release,
260}; 244};
@@ -262,7 +246,7 @@ const struct file_operations v9fs_dir_operations = {
262const struct file_operations v9fs_dir_operations_dotl = { 246const struct file_operations v9fs_dir_operations_dotl = {
263 .read = generic_read_dir, 247 .read = generic_read_dir,
264 .llseek = generic_file_llseek, 248 .llseek = generic_file_llseek,
265 .readdir = v9fs_dir_readdir_dotl, 249 .iterate = v9fs_dir_readdir_dotl,
266 .open = v9fs_file_open, 250 .open = v9fs_file_open,
267 .release = v9fs_dir_release, 251 .release = v9fs_dir_release,
268 .fsync = v9fs_file_fsync_dotl, 252 .fsync = v9fs_file_fsync_dotl,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index d86edc8d3fd0..25b018efb8ab 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1054,13 +1054,11 @@ static int
1054v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1054v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1055 struct kstat *stat) 1055 struct kstat *stat)
1056{ 1056{
1057 int err;
1058 struct v9fs_session_info *v9ses; 1057 struct v9fs_session_info *v9ses;
1059 struct p9_fid *fid; 1058 struct p9_fid *fid;
1060 struct p9_wstat *st; 1059 struct p9_wstat *st;
1061 1060
1062 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); 1061 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1063 err = -EPERM;
1064 v9ses = v9fs_dentry2v9ses(dentry); 1062 v9ses = v9fs_dentry2v9ses(dentry);
1065 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 1063 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1066 generic_fillattr(dentry->d_inode, stat); 1064 generic_fillattr(dentry->d_inode, stat);
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index c45e016b190f..3c28cdfb8c47 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -167,9 +167,13 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
167 167
168const struct xattr_handler *v9fs_xattr_handlers[] = { 168const struct xattr_handler *v9fs_xattr_handlers[] = {
169 &v9fs_xattr_user_handler, 169 &v9fs_xattr_user_handler,
170 &v9fs_xattr_trusted_handler,
170#ifdef CONFIG_9P_FS_POSIX_ACL 171#ifdef CONFIG_9P_FS_POSIX_ACL
171 &v9fs_xattr_acl_access_handler, 172 &v9fs_xattr_acl_access_handler,
172 &v9fs_xattr_acl_default_handler, 173 &v9fs_xattr_acl_default_handler,
173#endif 174#endif
175#ifdef CONFIG_9P_FS_SECURITY
176 &v9fs_xattr_security_handler,
177#endif
174 NULL 178 NULL
175}; 179};
diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h
index eec348a3df71..d3e2ea3840be 100644
--- a/fs/9p/xattr.h
+++ b/fs/9p/xattr.h
@@ -20,6 +20,8 @@
20 20
21extern const struct xattr_handler *v9fs_xattr_handlers[]; 21extern const struct xattr_handler *v9fs_xattr_handlers[];
22extern struct xattr_handler v9fs_xattr_user_handler; 22extern struct xattr_handler v9fs_xattr_user_handler;
23extern struct xattr_handler v9fs_xattr_trusted_handler;
24extern struct xattr_handler v9fs_xattr_security_handler;
23extern const struct xattr_handler v9fs_xattr_acl_access_handler; 25extern const struct xattr_handler v9fs_xattr_acl_access_handler;
24extern const struct xattr_handler v9fs_xattr_acl_default_handler; 26extern const struct xattr_handler v9fs_xattr_acl_default_handler;
25 27
diff --git a/fs/9p/xattr_security.c b/fs/9p/xattr_security.c
new file mode 100644
index 000000000000..cb247a142a6e
--- /dev/null
+++ b/fs/9p/xattr_security.c
@@ -0,0 +1,80 @@
1/*
2 * Copyright IBM Corporation, 2010
3 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2.1 of the GNU Lesser General Public License
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 */
14
15
16#include <linux/module.h>
17#include <linux/string.h>
18#include <linux/fs.h>
19#include <linux/slab.h>
20#include "xattr.h"
21
22static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
23 void *buffer, size_t size, int type)
24{
25 int retval;
26 char *full_name;
27 size_t name_len;
28 size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
29
30 if (name == NULL)
31 return -EINVAL;
32
33 if (strcmp(name, "") == 0)
34 return -EINVAL;
35
36 name_len = strlen(name);
37 full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
38 if (!full_name)
39 return -ENOMEM;
40 memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
41 memcpy(full_name+prefix_len, name, name_len);
42 full_name[prefix_len + name_len] = '\0';
43
44 retval = v9fs_xattr_get(dentry, full_name, buffer, size);
45 kfree(full_name);
46 return retval;
47}
48
49static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
50 const void *value, size_t size, int flags, int type)
51{
52 int retval;
53 char *full_name;
54 size_t name_len;
55 size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
56
57 if (name == NULL)
58 return -EINVAL;
59
60 if (strcmp(name, "") == 0)
61 return -EINVAL;
62
63 name_len = strlen(name);
64 full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
65 if (!full_name)
66 return -ENOMEM;
67 memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
68 memcpy(full_name + prefix_len, name, name_len);
69 full_name[prefix_len + name_len] = '\0';
70
71 retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
72 kfree(full_name);
73 return retval;
74}
75
76struct xattr_handler v9fs_xattr_security_handler = {
77 .prefix = XATTR_SECURITY_PREFIX,
78 .get = v9fs_xattr_security_get,
79 .set = v9fs_xattr_security_set,
80};
diff --git a/fs/9p/xattr_trusted.c b/fs/9p/xattr_trusted.c
new file mode 100644
index 000000000000..e30d33b8a3fb
--- /dev/null
+++ b/fs/9p/xattr_trusted.c
@@ -0,0 +1,80 @@
1/*
2 * Copyright IBM Corporation, 2010
3 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2.1 of the GNU Lesser General Public License
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 */
14
15
16#include <linux/module.h>
17#include <linux/string.h>
18#include <linux/fs.h>
19#include <linux/slab.h>
20#include "xattr.h"
21
22static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
23 void *buffer, size_t size, int type)
24{
25 int retval;
26 char *full_name;
27 size_t name_len;
28 size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
29
30 if (name == NULL)
31 return -EINVAL;
32
33 if (strcmp(name, "") == 0)
34 return -EINVAL;
35
36 name_len = strlen(name);
37 full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
38 if (!full_name)
39 return -ENOMEM;
40 memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
41 memcpy(full_name+prefix_len, name, name_len);
42 full_name[prefix_len + name_len] = '\0';
43
44 retval = v9fs_xattr_get(dentry, full_name, buffer, size);
45 kfree(full_name);
46 return retval;
47}
48
49static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
50 const void *value, size_t size, int flags, int type)
51{
52 int retval;
53 char *full_name;
54 size_t name_len;
55 size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
56
57 if (name == NULL)
58 return -EINVAL;
59
60 if (strcmp(name, "") == 0)
61 return -EINVAL;
62
63 name_len = strlen(name);
64 full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
65 if (!full_name)
66 return -ENOMEM;
67 memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
68 memcpy(full_name + prefix_len, name, name_len);
69 full_name[prefix_len + name_len] = '\0';
70
71 retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
72 kfree(full_name);
73 return retval;
74}
75
76struct xattr_handler v9fs_xattr_trusted_handler = {
77 .prefix = XATTR_TRUSTED_PREFIX,
78 .get = v9fs_xattr_trusted_get,
79 .set = v9fs_xattr_trusted_set,
80};