diff options
Diffstat (limited to 'security/tomoyo/tomoyo.c')
-rw-r--r-- | security/tomoyo/tomoyo.c | 142 |
1 files changed, 98 insertions, 44 deletions
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 2aceebf5f354..dedd97d0c163 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -11,8 +11,6 @@ | |||
11 | 11 | ||
12 | #include <linux/security.h> | 12 | #include <linux/security.h> |
13 | #include "common.h" | 13 | #include "common.h" |
14 | #include "tomoyo.h" | ||
15 | #include "realpath.h" | ||
16 | 14 | ||
17 | static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) | 15 | static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) |
18 | { | 16 | { |
@@ -23,21 +21,23 @@ static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) | |||
23 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, | 21 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, |
24 | gfp_t gfp) | 22 | gfp_t gfp) |
25 | { | 23 | { |
26 | /* | 24 | struct tomoyo_domain_info *domain = old->security; |
27 | * Since "struct tomoyo_domain_info *" is a sharable pointer, | 25 | new->security = domain; |
28 | * we don't need to duplicate. | 26 | if (domain) |
29 | */ | 27 | atomic_inc(&domain->users); |
30 | new->security = old->security; | ||
31 | return 0; | 28 | return 0; |
32 | } | 29 | } |
33 | 30 | ||
34 | static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) | 31 | static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) |
35 | { | 32 | { |
36 | /* | 33 | tomoyo_cred_prepare(new, old, 0); |
37 | * Since "struct tomoyo_domain_info *" is a sharable pointer, | 34 | } |
38 | * we don't need to duplicate. | 35 | |
39 | */ | 36 | static void tomoyo_cred_free(struct cred *cred) |
40 | new->security = old->security; | 37 | { |
38 | struct tomoyo_domain_info *domain = cred->security; | ||
39 | if (domain) | ||
40 | atomic_dec(&domain->users); | ||
41 | } | 41 | } |
42 | 42 | ||
43 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | 43 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) |
@@ -61,6 +61,14 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | |||
61 | if (!tomoyo_policy_loaded) | 61 | if (!tomoyo_policy_loaded) |
62 | tomoyo_load_policy(bprm->filename); | 62 | tomoyo_load_policy(bprm->filename); |
63 | /* | 63 | /* |
64 | * Release reference to "struct tomoyo_domain_info" stored inside | ||
65 | * "bprm->cred->security". New reference to "struct tomoyo_domain_info" | ||
66 | * stored inside "bprm->cred->security" will be acquired later inside | ||
67 | * tomoyo_find_next_domain(). | ||
68 | */ | ||
69 | atomic_dec(&((struct tomoyo_domain_info *) | ||
70 | bprm->cred->security)->users); | ||
71 | /* | ||
64 | * Tell tomoyo_bprm_check_security() is called for the first time of an | 72 | * Tell tomoyo_bprm_check_security() is called for the first time of an |
65 | * execve operation. | 73 | * execve operation. |
66 | */ | 74 | */ |
@@ -76,8 +84,12 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | |||
76 | * Execute permission is checked against pathname passed to do_execve() | 84 | * Execute permission is checked against pathname passed to do_execve() |
77 | * using current domain. | 85 | * using current domain. |
78 | */ | 86 | */ |
79 | if (!domain) | 87 | if (!domain) { |
80 | return tomoyo_find_next_domain(bprm); | 88 | const int idx = tomoyo_read_lock(); |
89 | const int err = tomoyo_find_next_domain(bprm); | ||
90 | tomoyo_read_unlock(idx); | ||
91 | return err; | ||
92 | } | ||
81 | /* | 93 | /* |
82 | * Read permission is checked against interpreters using next domain. | 94 | * Read permission is checked against interpreters using next domain. |
83 | */ | 95 | */ |
@@ -87,67 +99,56 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | |||
87 | static int tomoyo_path_truncate(struct path *path, loff_t length, | 99 | static int tomoyo_path_truncate(struct path *path, loff_t length, |
88 | unsigned int time_attrs) | 100 | unsigned int time_attrs) |
89 | { | 101 | { |
90 | return tomoyo_check_1path_perm(tomoyo_domain(), | 102 | return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); |
91 | TOMOYO_TYPE_TRUNCATE_ACL, | ||
92 | path); | ||
93 | } | 103 | } |
94 | 104 | ||
95 | static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) | 105 | static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) |
96 | { | 106 | { |
97 | struct path path = { parent->mnt, dentry }; | 107 | struct path path = { parent->mnt, dentry }; |
98 | return tomoyo_check_1path_perm(tomoyo_domain(), | 108 | return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path); |
99 | TOMOYO_TYPE_UNLINK_ACL, | ||
100 | &path); | ||
101 | } | 109 | } |
102 | 110 | ||
103 | static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, | 111 | static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, |
104 | int mode) | 112 | int mode) |
105 | { | 113 | { |
106 | struct path path = { parent->mnt, dentry }; | 114 | struct path path = { parent->mnt, dentry }; |
107 | return tomoyo_check_1path_perm(tomoyo_domain(), | 115 | return tomoyo_path_perm(TOMOYO_TYPE_MKDIR, &path); |
108 | TOMOYO_TYPE_MKDIR_ACL, | ||
109 | &path); | ||
110 | } | 116 | } |
111 | 117 | ||
112 | static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) | 118 | static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) |
113 | { | 119 | { |
114 | struct path path = { parent->mnt, dentry }; | 120 | struct path path = { parent->mnt, dentry }; |
115 | return tomoyo_check_1path_perm(tomoyo_domain(), | 121 | return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path); |
116 | TOMOYO_TYPE_RMDIR_ACL, | ||
117 | &path); | ||
118 | } | 122 | } |
119 | 123 | ||
120 | static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, | 124 | static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, |
121 | const char *old_name) | 125 | const char *old_name) |
122 | { | 126 | { |
123 | struct path path = { parent->mnt, dentry }; | 127 | struct path path = { parent->mnt, dentry }; |
124 | return tomoyo_check_1path_perm(tomoyo_domain(), | 128 | return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path); |
125 | TOMOYO_TYPE_SYMLINK_ACL, | ||
126 | &path); | ||
127 | } | 129 | } |
128 | 130 | ||
129 | static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, | 131 | static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, |
130 | int mode, unsigned int dev) | 132 | int mode, unsigned int dev) |
131 | { | 133 | { |
132 | struct path path = { parent->mnt, dentry }; | 134 | struct path path = { parent->mnt, dentry }; |
133 | int type = TOMOYO_TYPE_CREATE_ACL; | 135 | int type = TOMOYO_TYPE_CREATE; |
134 | 136 | ||
135 | switch (mode & S_IFMT) { | 137 | switch (mode & S_IFMT) { |
136 | case S_IFCHR: | 138 | case S_IFCHR: |
137 | type = TOMOYO_TYPE_MKCHAR_ACL; | 139 | type = TOMOYO_TYPE_MKCHAR; |
138 | break; | 140 | break; |
139 | case S_IFBLK: | 141 | case S_IFBLK: |
140 | type = TOMOYO_TYPE_MKBLOCK_ACL; | 142 | type = TOMOYO_TYPE_MKBLOCK; |
141 | break; | 143 | break; |
142 | case S_IFIFO: | 144 | case S_IFIFO: |
143 | type = TOMOYO_TYPE_MKFIFO_ACL; | 145 | type = TOMOYO_TYPE_MKFIFO; |
144 | break; | 146 | break; |
145 | case S_IFSOCK: | 147 | case S_IFSOCK: |
146 | type = TOMOYO_TYPE_MKSOCK_ACL; | 148 | type = TOMOYO_TYPE_MKSOCK; |
147 | break; | 149 | break; |
148 | } | 150 | } |
149 | return tomoyo_check_1path_perm(tomoyo_domain(), | 151 | return tomoyo_path_perm(type, &path); |
150 | type, &path); | ||
151 | } | 152 | } |
152 | 153 | ||
153 | static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, | 154 | static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, |
@@ -155,9 +156,7 @@ static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, | |||
155 | { | 156 | { |
156 | struct path path1 = { new_dir->mnt, old_dentry }; | 157 | struct path path1 = { new_dir->mnt, old_dentry }; |
157 | struct path path2 = { new_dir->mnt, new_dentry }; | 158 | struct path path2 = { new_dir->mnt, new_dentry }; |
158 | return tomoyo_check_2path_perm(tomoyo_domain(), | 159 | return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); |
159 | TOMOYO_TYPE_LINK_ACL, | ||
160 | &path1, &path2); | ||
161 | } | 160 | } |
162 | 161 | ||
163 | static int tomoyo_path_rename(struct path *old_parent, | 162 | static int tomoyo_path_rename(struct path *old_parent, |
@@ -167,16 +166,14 @@ static int tomoyo_path_rename(struct path *old_parent, | |||
167 | { | 166 | { |
168 | struct path path1 = { old_parent->mnt, old_dentry }; | 167 | struct path path1 = { old_parent->mnt, old_dentry }; |
169 | struct path path2 = { new_parent->mnt, new_dentry }; | 168 | struct path path2 = { new_parent->mnt, new_dentry }; |
170 | return tomoyo_check_2path_perm(tomoyo_domain(), | 169 | return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); |
171 | TOMOYO_TYPE_RENAME_ACL, | ||
172 | &path1, &path2); | ||
173 | } | 170 | } |
174 | 171 | ||
175 | static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, | 172 | static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, |
176 | unsigned long arg) | 173 | unsigned long arg) |
177 | { | 174 | { |
178 | if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) | 175 | if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) |
179 | return tomoyo_check_rewrite_permission(tomoyo_domain(), file); | 176 | return tomoyo_check_rewrite_permission(file); |
180 | return 0; | 177 | return 0; |
181 | } | 178 | } |
182 | 179 | ||
@@ -189,6 +186,51 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred) | |||
189 | return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); | 186 | return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); |
190 | } | 187 | } |
191 | 188 | ||
189 | static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, | ||
190 | unsigned long arg) | ||
191 | { | ||
192 | return tomoyo_path_perm(TOMOYO_TYPE_IOCTL, &file->f_path); | ||
193 | } | ||
194 | |||
195 | static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, | ||
196 | mode_t mode) | ||
197 | { | ||
198 | struct path path = { mnt, dentry }; | ||
199 | return tomoyo_path_perm(TOMOYO_TYPE_CHMOD, &path); | ||
200 | } | ||
201 | |||
202 | static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) | ||
203 | { | ||
204 | int error = 0; | ||
205 | if (uid != (uid_t) -1) | ||
206 | error = tomoyo_path_perm(TOMOYO_TYPE_CHOWN, path); | ||
207 | if (!error && gid != (gid_t) -1) | ||
208 | error = tomoyo_path_perm(TOMOYO_TYPE_CHGRP, path); | ||
209 | return error; | ||
210 | } | ||
211 | |||
212 | static int tomoyo_path_chroot(struct path *path) | ||
213 | { | ||
214 | return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path); | ||
215 | } | ||
216 | |||
217 | static int tomoyo_sb_mount(char *dev_name, struct path *path, | ||
218 | char *type, unsigned long flags, void *data) | ||
219 | { | ||
220 | return tomoyo_path_perm(TOMOYO_TYPE_MOUNT, path); | ||
221 | } | ||
222 | |||
223 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) | ||
224 | { | ||
225 | struct path path = { mnt, mnt->mnt_root }; | ||
226 | return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path); | ||
227 | } | ||
228 | |||
229 | static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) | ||
230 | { | ||
231 | return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); | ||
232 | } | ||
233 | |||
192 | /* | 234 | /* |
193 | * tomoyo_security_ops is a "struct security_operations" which is used for | 235 | * tomoyo_security_ops is a "struct security_operations" which is used for |
194 | * registering TOMOYO. | 236 | * registering TOMOYO. |
@@ -198,6 +240,7 @@ static struct security_operations tomoyo_security_ops = { | |||
198 | .cred_alloc_blank = tomoyo_cred_alloc_blank, | 240 | .cred_alloc_blank = tomoyo_cred_alloc_blank, |
199 | .cred_prepare = tomoyo_cred_prepare, | 241 | .cred_prepare = tomoyo_cred_prepare, |
200 | .cred_transfer = tomoyo_cred_transfer, | 242 | .cred_transfer = tomoyo_cred_transfer, |
243 | .cred_free = tomoyo_cred_free, | ||
201 | .bprm_set_creds = tomoyo_bprm_set_creds, | 244 | .bprm_set_creds = tomoyo_bprm_set_creds, |
202 | .bprm_check_security = tomoyo_bprm_check_security, | 245 | .bprm_check_security = tomoyo_bprm_check_security, |
203 | .file_fcntl = tomoyo_file_fcntl, | 246 | .file_fcntl = tomoyo_file_fcntl, |
@@ -210,8 +253,18 @@ static struct security_operations tomoyo_security_ops = { | |||
210 | .path_mknod = tomoyo_path_mknod, | 253 | .path_mknod = tomoyo_path_mknod, |
211 | .path_link = tomoyo_path_link, | 254 | .path_link = tomoyo_path_link, |
212 | .path_rename = tomoyo_path_rename, | 255 | .path_rename = tomoyo_path_rename, |
256 | .file_ioctl = tomoyo_file_ioctl, | ||
257 | .path_chmod = tomoyo_path_chmod, | ||
258 | .path_chown = tomoyo_path_chown, | ||
259 | .path_chroot = tomoyo_path_chroot, | ||
260 | .sb_mount = tomoyo_sb_mount, | ||
261 | .sb_umount = tomoyo_sb_umount, | ||
262 | .sb_pivotroot = tomoyo_sb_pivotroot, | ||
213 | }; | 263 | }; |
214 | 264 | ||
265 | /* Lock for GC. */ | ||
266 | struct srcu_struct tomoyo_ss; | ||
267 | |||
215 | static int __init tomoyo_init(void) | 268 | static int __init tomoyo_init(void) |
216 | { | 269 | { |
217 | struct cred *cred = (struct cred *) current_cred(); | 270 | struct cred *cred = (struct cred *) current_cred(); |
@@ -219,7 +272,8 @@ static int __init tomoyo_init(void) | |||
219 | if (!security_module_enable(&tomoyo_security_ops)) | 272 | if (!security_module_enable(&tomoyo_security_ops)) |
220 | return 0; | 273 | return 0; |
221 | /* register ourselves with the security framework */ | 274 | /* register ourselves with the security framework */ |
222 | if (register_security(&tomoyo_security_ops)) | 275 | if (register_security(&tomoyo_security_ops) || |
276 | init_srcu_struct(&tomoyo_ss)) | ||
223 | panic("Failure registering TOMOYO Linux"); | 277 | panic("Failure registering TOMOYO Linux"); |
224 | printk(KERN_INFO "TOMOYO Linux initialized\n"); | 278 | printk(KERN_INFO "TOMOYO Linux initialized\n"); |
225 | cred->security = &tomoyo_kernel_domain; | 279 | cred->security = &tomoyo_kernel_domain; |