1
Index: b/security/apparmor/lsm.c
2
===================================================================
3
--- a/security/apparmor/lsm.c
4
+++ b/security/apparmor/lsm.c
5
@@ -251,7 +251,7 @@ out:
8
static int aa_permission(struct inode *inode, struct dentry *dentry,
9
- struct vfsmount *mnt, int mask, int leaf)
10
+ struct vfsmount *mnt, int mask, int check)
14
@@ -259,7 +259,7 @@ static int aa_permission(struct inode *i
15
struct aa_profile *profile = aa_get_profile(current);
18
- error = aa_perm(profile, dentry, mnt, mask, leaf);
19
+ error = aa_perm(profile, dentry, mnt, mask, check);
20
aa_put_profile(profile);
23
@@ -268,7 +268,7 @@ static int aa_permission(struct inode *i
24
static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
25
struct vfsmount *mnt, int mask)
27
- return aa_permission(dir, dentry, mnt, MAY_WRITE, 1);
28
+ return aa_permission(dir, dentry, mnt, MAY_WRITE, AA_CHECK_LEAF);
31
static int apparmor_inode_link(struct dentry *old_dentry,
32
@@ -298,19 +298,19 @@ static int apparmor_inode_unlink(struct
33
struct dentry *dentry,
36
- return aa_permission(dir, dentry, mnt, MAY_WRITE, 1);
37
+ return aa_permission(dir, dentry, mnt, MAY_WRITE, AA_CHECK_LEAF);
40
static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
41
struct vfsmount *mnt, const char *old_name)
43
- return aa_permission(dir, dentry, mnt, MAY_WRITE, 1);
44
+ return aa_permission(dir, dentry, mnt, MAY_WRITE, AA_CHECK_LEAF);
47
static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
48
struct vfsmount *mnt, int mode, dev_t dev)
50
- return aa_permission(dir, dentry, mnt, MAY_WRITE, 1);
51
+ return aa_permission(dir, dentry, mnt, MAY_WRITE, AA_CHECK_LEAF);
54
static int apparmor_inode_rename(struct inode *old_dir,
55
@@ -331,11 +331,11 @@ static int apparmor_inode_rename(struct
58
error = aa_perm(profile, old_dentry, old_mnt,
59
- MAY_READ | MAY_WRITE, 1);
60
+ MAY_READ | MAY_WRITE, AA_CHECK_LEAF);
62
if (!error && new_mnt)
63
error = aa_perm(profile, new_dentry, new_mnt,
65
+ MAY_WRITE, AA_CHECK_LEAF);
68
aa_put_profile(profile);
69
@@ -395,16 +395,17 @@ out:
71
static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
72
const char *name, const char *operation,
74
+ int mask, struct file *file)
78
if (mnt && mediated_filesystem(dentry->d_inode)) {
79
struct aa_profile *profile = aa_get_profile(current);
80
+ int check = file ? AA_CHECK_FD : 0;
83
error = aa_perm_xattr(profile, dentry, mnt, name,
85
+ operation, mask, check);
86
aa_put_profile(profile);
89
@@ -413,27 +414,32 @@ static int aa_xattr_permission(struct de
91
static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
92
char *name, void *value, size_t size,
94
+ int flags, struct file *file)
96
- return aa_xattr_permission(dentry, mnt, name, "xattr set", MAY_WRITE);
97
+ return aa_xattr_permission(dentry, mnt, name, "xattr set", MAY_WRITE,
101
static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
103
+ char *name, struct file *file)
105
- return aa_xattr_permission(dentry, mnt, name, "xattr get", MAY_READ);
106
+ return aa_xattr_permission(dentry, mnt, name, "xattr get", MAY_READ,
110
-static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
111
+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
114
- return aa_xattr_permission(dentry, mnt, NULL, "xattr list", MAY_READ);
115
+ return aa_xattr_permission(dentry, mnt, NULL, "xattr list", MAY_READ,
119
static int apparmor_inode_removexattr(struct dentry *dentry,
120
- struct vfsmount *mnt, char *name)
121
+ struct vfsmount *mnt, char *name,
124
return aa_xattr_permission(dentry, mnt, name, "xattr remove",
129
static int apparmor_file_permission(struct file *file, int mask)
130
@@ -459,7 +465,8 @@ static int apparmor_file_permission(stru
133
mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
134
- error = aa_permission(dentry->d_inode, dentry, mnt, mask, 1);
135
+ error = aa_permission(dentry->d_inode, dentry, mnt, mask,
136
+ AA_CHECK_LEAF | AA_CHECK_FD);
138
aa_put_profile(profile);
140
@@ -520,7 +527,8 @@ static inline int aa_mmap(struct file *f
141
mask |= AA_EXEC_MMAP;
143
dentry = file->f_dentry;
144
- return aa_permission(dentry->d_inode, dentry, file->f_vfsmnt, mask, 1);
145
+ return aa_permission(dentry->d_inode, dentry, file->f_vfsmnt, mask,
146
+ AA_CHECK_LEAF | AA_CHECK_FD);
149
static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
150
Index: b/security/apparmor/main.c
151
===================================================================
152
--- a/security/apparmor/main.c
153
+++ b/security/apparmor/main.c
154
@@ -137,13 +137,12 @@ static int aa_link_denied(struct aa_prof
157
static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
158
- char **buffer, int is_dir)
159
+ char **buffer, int check)
163
+ int is_dir, size = 256;
165
- /* Make sure is_dir is either 0 or 1. */
167
+ is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
170
char *buf = kmalloc(size, GFP_KERNEL);
171
@@ -190,19 +189,19 @@ static inline void aa_put_name_buffer(ch
173
static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
174
struct vfsmount *mnt, struct aa_audit *sa, int mask,
175
- int is_dir, int accessed_through_fd)
179
int denied_mask, error;
181
- sa->name = aa_get_name(dentry, mnt, &buffer, is_dir);
182
+ sa->name = aa_get_name(dentry, mnt, &buffer, check);
184
if (IS_ERR(sa->name)) {
186
* deleted files are given a pass on permission checks when
187
* accessed through a file descriptor.
189
- if (PTR_ERR(sa->name) == -ENOENT && accessed_through_fd)
190
+ if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
193
denied_mask = PTR_ERR(sa->name);
194
@@ -532,7 +531,8 @@ out:
195
int aa_attr(struct aa_profile *profile, struct dentry *dentry,
196
struct vfsmount *mnt, struct iattr *iattr)
199
+ struct inode *inode = dentry->d_inode;
203
sa.type = AA_AUDITTYPE_ATTR;
204
@@ -540,9 +540,13 @@ int aa_attr(struct aa_profile *profile,
206
sa.gfp_mask = GFP_KERNEL;
208
- error = aa_perm_dentry(profile, dentry, mnt, &sa, MAY_WRITE,
209
- S_ISDIR(dentry->d_inode->i_mode),
210
- iattr->ia_valid & ATTR_FILE);
212
+ if (inode && S_ISDIR(inode->i_mode))
213
+ check |= AA_CHECK_DIR;
214
+ if (iattr->ia_valid & ATTR_FILE)
215
+ check |= AA_CHECK_FD;
217
+ error = aa_perm_dentry(profile, dentry, mnt, &sa, MAY_WRITE, check);
221
@@ -558,8 +562,9 @@ int aa_attr(struct aa_profile *profile,
223
int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
224
struct vfsmount *mnt, const char *operation,
225
- const char *xattr_name, int mask)
226
+ const char *xattr_name, int mask, int check)
228
+ struct inode *inode = dentry->d_inode;
232
@@ -569,9 +574,10 @@ int aa_perm_xattr(struct aa_profile *pro
234
sa.gfp_mask = GFP_KERNEL;
236
- error = aa_perm_dentry(profile, dentry, mnt, &sa, mask,
237
- S_ISDIR(dentry->d_inode->i_mode),
239
+ if (inode && S_ISDIR(inode->i_mode))
240
+ check |= AA_CHECK_DIR;
242
+ error = aa_perm_dentry(profile, dentry, mnt, &sa, mask, check);
246
@@ -588,13 +594,16 @@ int aa_perm_xattr(struct aa_profile *pro
247
* profile. Result, %0 (success), -ve (error)
249
int aa_perm(struct aa_profile *profile, struct dentry *dentry,
250
- struct vfsmount *mnt, int mask, int leaf)
251
+ struct vfsmount *mnt, int mask, int check)
253
struct inode *inode = dentry->d_inode;
257
- if (!leaf && inode && S_ISDIR(inode->i_mode)) {
258
+ if (inode && S_ISDIR(inode->i_mode))
259
+ check |= AA_CHECK_DIR;
261
+ if ((check & (AA_CHECK_DIR | AA_CHECK_LEAF)) == AA_CHECK_DIR) {
263
* If checking a non-leaf directory, allow traverse and
264
* write access: we do not require profile access to
265
@@ -612,9 +621,7 @@ int aa_perm(struct aa_profile *profile,
268
sa.gfp_mask = GFP_KERNEL;
269
- error = aa_perm_dentry(profile, dentry, mnt, &sa, mask,
270
- inode && S_ISDIR(inode->i_mode),
272
+ error = aa_perm_dentry(profile, dentry, mnt, &sa, mask, check);
276
@@ -642,8 +649,7 @@ int aa_perm_dir(struct aa_profile *profi
278
sa.gfp_mask = GFP_KERNEL;
280
- return aa_perm_dentry(profile, dentry, mnt, &sa, mask, 1,
282
+ return aa_perm_dentry(profile, dentry, mnt, &sa, mask, AA_CHECK_DIR);
286
Index: b/security/apparmor/apparmor.h
287
===================================================================
288
--- a/security/apparmor/apparmor.h
289
+++ b/security/apparmor/apparmor.h
290
@@ -204,6 +204,11 @@ struct aa_audit {
291
"LOGPROF-HINT " hint " " fmt, ##args);\
294
+/* Flags for the permission check functions */
295
+#define AA_CHECK_LEAF 1 /* this is the leaf lookup component */
296
+#define AA_CHECK_FD 2 /* coming from a file descriptor */
297
+#define AA_CHECK_DIR 4 /* file type is directory */
300
extern int alloc_null_complain_profile(void);
301
extern void free_null_complain_profile(void);
302
@@ -218,10 +223,10 @@ extern int aa_attr(struct aa_profile *pr
303
struct vfsmount *mnt, struct iattr *iattr);
304
extern int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
305
struct vfsmount *mnt, const char *operation,
306
- const char *xattr_xattr, int mask);
307
+ const char *xattr_xattr, int mask, int check);
308
extern int aa_capability(struct aa_profile *profile, int cap);
309
extern int aa_perm(struct aa_profile *profile, struct dentry *dentry,
310
- struct vfsmount *mnt, int mask, int leaf);
311
+ struct vfsmount *mnt, int mask, int check);
312
extern int aa_perm_dir(struct aa_profile *profile, struct dentry *dentry,
313
struct vfsmount *mnt, const char *operation, int mask);
314
extern int aa_link(struct aa_profile *profile,
315
Index: b/fs/nfsd/vfs.c
316
===================================================================
319
@@ -383,7 +383,7 @@ static ssize_t nfsd_getxattr(struct dent
323
- buflen = vfs_getxattr(dentry, mnt, key, NULL, 0);
324
+ buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
328
@@ -391,7 +391,7 @@ static ssize_t nfsd_getxattr(struct dent
332
- return vfs_getxattr(dentry, mnt, key, *buf, buflen);
333
+ return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
337
@@ -417,7 +417,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
341
- error = vfs_setxattr(dentry, mnt, key, buf, len, 0);
342
+ error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
346
@@ -1984,13 +1984,14 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
349
error = vfs_setxattr(fhp->fh_dentry, fhp->fh_export->ex_mnt,
350
- name, value, size,0);
351
+ name, value, size, 0, NULL);
353
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
356
error = vfs_removexattr(fhp->fh_dentry,
357
- fhp->fh_export->ex_mnt, name);
358
+ fhp->fh_export->ex_mnt, name,
360
if (error == -ENODATA)