]>
Commit | Line | Data |
---|---|---|
4d1e5b62 AF |
1 | From: Jeff Mahoney <jeffm@suse.com> |
2 | Subject: [PATCH] vfs: introduce path_permission() | |
3 | ||
4 | 2.6.27 eliminated the nameidata parameter from permission and replaced | |
5 | several call sites with inode_permission. This keeps the information | |
6 | required by AppArmor from reaching it. | |
7 | ||
8 | The following patch factors out the permission assessment part of | |
9 | inode_permission into __inode_permission and adds a path_permission | |
10 | function that takes a struct path instead of a struct inode and passes | |
11 | it to security_path_permission instead of security_inode_permission. | |
12 | ||
13 | All of the call sites that had access to a struct path whether by | |
14 | itself or via a file or nameidata (and used it) in 2.6.26 are changed | |
15 | to use the path_permission call. | |
16 | ||
17 | Signed-off-by: Jeff Mahoney <jeffm@suse.com> | |
18 | --- | |
19 | fs/inotify_user.c | 2 +- | |
20 | fs/namei.c | 32 ++++++++++++++++++++++++-------- | |
21 | fs/open.c | 10 +++++----- | |
22 | include/linux/fs.h | 5 +++++ | |
23 | 4 files changed, 35 insertions(+), 14 deletions(-) | |
24 | ||
25 | --- a/fs/inotify_user.c | |
26 | +++ b/fs/inotify_user.c | |
27 | @@ -372,7 +372,7 @@ static int find_inode(const char __user | |
28 | if (error) | |
29 | return error; | |
30 | /* you can only watch an inode if you have read permissions on it */ | |
31 | - error = inode_permission(path->dentry->d_inode, MAY_READ); | |
32 | + error = path_permission(path, MAY_READ); | |
33 | if (error) | |
34 | path_put(path); | |
35 | return error; | |
36 | --- a/fs/namei.c | |
37 | +++ b/fs/namei.c | |
38 | @@ -227,7 +227,7 @@ int generic_permission(struct inode *ino | |
39 | return -EACCES; | |
40 | } | |
41 | ||
42 | -int inode_permission(struct inode *inode, int mask) | |
43 | +static int __inode_permission(struct inode *inode, int mask) | |
44 | { | |
45 | int retval; | |
46 | int submask = mask; | |
47 | @@ -273,7 +273,12 @@ int inode_permission(struct inode *inode | |
48 | if (retval) | |
49 | return retval; | |
50 | ||
51 | - retval = devcgroup_inode_permission(inode, mask); | |
52 | + return devcgroup_inode_permission(inode, mask); | |
53 | +} | |
54 | + | |
55 | +int inode_permission(struct inode *inode, int mask) | |
56 | +{ | |
57 | + int retval = __inode_permission(inode, mask); | |
58 | if (retval) | |
59 | return retval; | |
60 | ||
61 | @@ -281,6 +286,15 @@ int inode_permission(struct inode *inode | |
62 | mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND)); | |
63 | } | |
64 | ||
65 | +int path_permission(struct path *path, int mask) | |
66 | +{ | |
67 | + int retval = __inode_permission(path->dentry->d_inode, mask); | |
68 | + if (retval) | |
69 | + return retval; | |
70 | + return security_path_permission(path, | |
71 | + mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND)); | |
72 | +} | |
73 | + | |
74 | /** | |
75 | * vfs_permission - check for access rights to a given path | |
76 | * @nd: lookup result that describes the path | |
77 | @@ -293,7 +307,7 @@ int inode_permission(struct inode *inode | |
78 | */ | |
79 | int vfs_permission(struct nameidata *nd, int mask) | |
80 | { | |
81 | - return inode_permission(nd->path.dentry->d_inode, mask); | |
82 | + return path_permission(&nd->path, mask); | |
83 | } | |
84 | ||
85 | /** | |
86 | @@ -310,7 +324,7 @@ int vfs_permission(struct nameidata *nd, | |
87 | */ | |
88 | int file_permission(struct file *file, int mask) | |
89 | { | |
90 | - return inode_permission(file->f_path.dentry->d_inode, mask); | |
91 | + return path_permission(&file->f_path, mask); | |
92 | } | |
93 | ||
94 | /* | |
95 | @@ -452,8 +466,9 @@ static struct dentry * cached_lookup(str | |
96 | * short-cut DAC fails, then call permission() to do more | |
97 | * complete permission check. | |
98 | */ | |
99 | -static int exec_permission_lite(struct inode *inode) | |
100 | +static int exec_permission_lite(struct path *path) | |
101 | { | |
102 | + struct inode *inode = path->dentry->d_inode; | |
103 | umode_t mode = inode->i_mode; | |
104 | ||
105 | if (inode->i_op && inode->i_op->permission) | |
106 | @@ -478,7 +493,7 @@ static int exec_permission_lite(struct i | |
107 | ||
108 | return -EACCES; | |
109 | ok: | |
110 | - return security_inode_permission(inode, MAY_EXEC); | |
111 | + return security_path_permission(path, MAY_EXEC); | |
112 | } | |
113 | ||
114 | /* | |
115 | @@ -875,7 +890,7 @@ static int __link_path_walk(const char * | |
116 | unsigned int c; | |
117 | ||
118 | nd->flags |= LOOKUP_CONTINUE; | |
119 | - err = exec_permission_lite(inode); | |
120 | + err = exec_permission_lite(&nd->path); | |
121 | if (err == -EAGAIN) | |
122 | err = vfs_permission(nd, MAY_EXEC); | |
123 | if (err) | |
124 | @@ -1250,7 +1265,7 @@ static struct dentry *lookup_hash(struct | |
125 | { | |
126 | int err; | |
127 | ||
128 | - err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC); | |
129 | + err = path_permission(&nd->path, MAY_EXEC); | |
130 | if (err) | |
131 | return ERR_PTR(err); | |
132 | return __lookup_hash(&nd->last, nd->path.dentry, nd); | |
133 | @@ -2907,6 +2922,7 @@ EXPORT_SYMBOL(page_symlink_inode_operati | |
134 | EXPORT_SYMBOL(path_lookup); | |
135 | EXPORT_SYMBOL(vfs_path_lookup); | |
136 | EXPORT_SYMBOL(inode_permission); | |
137 | +EXPORT_SYMBOL(path_permission); | |
138 | EXPORT_SYMBOL(vfs_permission); | |
139 | EXPORT_SYMBOL(file_permission); | |
140 | EXPORT_SYMBOL(unlock_rename); | |
141 | --- a/fs/open.c | |
142 | +++ b/fs/open.c | |
143 | @@ -248,7 +248,7 @@ static long do_sys_truncate(const char _ | |
144 | if (error) | |
145 | goto dput_and_out; | |
146 | ||
147 | - error = inode_permission(inode, MAY_WRITE); | |
148 | + error = path_permission(&path, MAY_WRITE); | |
149 | if (error) | |
150 | goto mnt_drop_write_and_out; | |
151 | ||
152 | @@ -493,7 +493,7 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con | |
153 | goto out_path_release; | |
154 | } | |
155 | ||
156 | - res = inode_permission(inode, mode | MAY_ACCESS); | |
157 | + res = path_permission(&path, mode | MAY_ACCESS); | |
158 | /* SuS v2 requires we report a read only fs too */ | |
159 | if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) | |
160 | goto out_path_release; | |
161 | @@ -536,7 +536,7 @@ SYSCALL_DEFINE1(chdir, const char __user | |
162 | if (error) | |
163 | goto out; | |
164 | ||
165 | - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); | |
166 | + error = path_permission(&path, MAY_EXEC | MAY_ACCESS); | |
167 | if (error) | |
168 | goto dput_and_out; | |
169 | ||
170 | @@ -565,7 +565,7 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd | |
171 | if (!S_ISDIR(inode->i_mode)) | |
172 | goto out_putf; | |
173 | ||
174 | - error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); | |
175 | + error = path_permission(&file->f_path, MAY_EXEC | MAY_ACCESS); | |
176 | if (!error) | |
177 | set_fs_pwd(current->fs, &file->f_path); | |
178 | out_putf: | |
179 | @@ -583,7 +583,7 @@ SYSCALL_DEFINE1(chroot, const char __use | |
180 | if (error) | |
181 | goto out; | |
182 | ||
183 | - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); | |
184 | + error = path_permission(&path, MAY_EXEC | MAY_ACCESS); | |
185 | if (error) | |
186 | goto dput_and_out; | |
187 | ||
188 | --- a/include/linux/fs.h | |
189 | +++ b/include/linux/fs.h | |
190 | @@ -1201,6 +1201,11 @@ extern void dentry_unhash(struct dentry | |
191 | extern int file_permission(struct file *, int); | |
192 | ||
193 | /* | |
194 | + * VFS path helper functions. | |
195 | + */ | |
196 | +extern int path_permission(struct path *, int); | |
197 | + | |
198 | +/* | |
199 | * File types | |
200 | * | |
201 | * NOTE! These match bits 12..15 of stat.st_mode |