diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2010-02-10 19:43:20 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-02-14 17:00:21 -0500 |
commit | ec8e6a4e062e2edebef91e930c20572c9f4c0dda (patch) | |
tree | 1c48fb2aa2220b3bdc138e0fb33e1ac632d0dffe /security | |
parent | 76bb0895d038be7bcdb6ccfcd2dd7deb30371d6b (diff) |
TOMOYO: Add refcounter on domain structure.
Add refcounter to "struct tomoyo_domain_info" since garbage collector needs to
determine whether this struct is referred by "struct cred"->security or not.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/tomoyo/common.h | 5 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 2 | ||||
-rw-r--r-- | security/tomoyo/tomoyo.c | 37 |
3 files changed, 28 insertions, 16 deletions
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f6aff59b088..521b4b5adda 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -234,6 +234,10 @@ struct tomoyo_acl_info { | |||
234 | * name of the domain to be created was too long or it could not allocate | 234 | * name of the domain to be created was too long or it could not allocate |
235 | * memory. If set to true, more than one process continued execve() | 235 | * memory. If set to true, more than one process continued execve() |
236 | * without domain transition. | 236 | * without domain transition. |
237 | * (9) "users" is an atomic_t that holds how many "struct cred"->security | ||
238 | * are referring this "struct tomoyo_domain_info". If is_deleted == true | ||
239 | * and users == 0, this struct will be kfree()d upon next garbage | ||
240 | * collection. | ||
237 | * | 241 | * |
238 | * A domain's lifecycle is an analogy of files on / directory. | 242 | * A domain's lifecycle is an analogy of files on / directory. |
239 | * Multiple domains with the same domainname cannot be created (as with | 243 | * Multiple domains with the same domainname cannot be created (as with |
@@ -252,6 +256,7 @@ struct tomoyo_domain_info { | |||
252 | bool quota_warned; /* Quota warnning flag. */ | 256 | bool quota_warned; /* Quota warnning flag. */ |
253 | bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ | 257 | bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ |
254 | bool transition_failed; /* Domain transition failed flag. */ | 258 | bool transition_failed; /* Domain transition failed flag. */ |
259 | atomic_t users; /* Number of referring credentials. */ | ||
255 | }; | 260 | }; |
256 | 261 | ||
257 | /* | 262 | /* |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index d60b8a61b0c..6f74b30d6bb 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -817,6 +817,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
817 | out: | 817 | out: |
818 | if (!domain) | 818 | if (!domain) |
819 | domain = old_domain; | 819 | domain = old_domain; |
820 | /* Update reference count on "struct tomoyo_domain_info". */ | ||
821 | atomic_inc(&domain->users); | ||
820 | bprm->cred->security = domain; | 822 | bprm->cred->security = domain; |
821 | kfree(real_program_name); | 823 | kfree(real_program_name); |
822 | kfree(symlink_program_name); | 824 | kfree(symlink_program_name); |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 8a0988dade7..87e82bfeac2 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -21,21 +21,23 @@ static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) | |||
21 | 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, |
22 | gfp_t gfp) | 22 | gfp_t gfp) |
23 | { | 23 | { |
24 | /* | 24 | struct tomoyo_domain_info *domain = old->security; |
25 | * Since "struct tomoyo_domain_info *" is a sharable pointer, | 25 | new->security = domain; |
26 | * we don't need to duplicate. | 26 | if (domain) |
27 | */ | 27 | atomic_inc(&domain->users); |
28 | new->security = old->security; | ||
29 | return 0; | 28 | return 0; |
30 | } | 29 | } |
31 | 30 | ||
32 | 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) |
33 | { | 32 | { |
34 | /* | 33 | tomoyo_cred_prepare(new, old, 0); |
35 | * Since "struct tomoyo_domain_info *" is a sharable pointer, | 34 | } |
36 | * we don't need to duplicate. | 35 | |
37 | */ | 36 | static void tomoyo_cred_free(struct cred *cred) |
38 | new->security = old->security; | 37 | { |
38 | struct tomoyo_domain_info *domain = cred->security; | ||
39 | if (domain) | ||
40 | atomic_dec(&domain->users); | ||
39 | } | 41 | } |
40 | 42 | ||
41 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | 43 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) |
@@ -59,6 +61,14 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | |||
59 | if (!tomoyo_policy_loaded) | 61 | if (!tomoyo_policy_loaded) |
60 | tomoyo_load_policy(bprm->filename); | 62 | tomoyo_load_policy(bprm->filename); |
61 | /* | 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 | /* | ||
62 | * 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 |
63 | * execve operation. | 73 | * execve operation. |
64 | */ | 74 | */ |
@@ -75,12 +85,6 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | |||
75 | * using current domain. | 85 | * using current domain. |
76 | */ | 86 | */ |
77 | if (!domain) { | 87 | if (!domain) { |
78 | /* | ||
79 | * We will need to protect whole execve() operation when GC | ||
80 | * starts kfree()ing "struct tomoyo_domain_info" because | ||
81 | * bprm->cred->security points to "struct tomoyo_domain_info" | ||
82 | * but "struct tomoyo_domain_info" does not have a refcounter. | ||
83 | */ | ||
84 | const int idx = tomoyo_read_lock(); | 88 | const int idx = tomoyo_read_lock(); |
85 | const int err = tomoyo_find_next_domain(bprm); | 89 | const int err = tomoyo_find_next_domain(bprm); |
86 | tomoyo_read_unlock(idx); | 90 | tomoyo_read_unlock(idx); |
@@ -265,6 +269,7 @@ static struct security_operations tomoyo_security_ops = { | |||
265 | .cred_alloc_blank = tomoyo_cred_alloc_blank, | 269 | .cred_alloc_blank = tomoyo_cred_alloc_blank, |
266 | .cred_prepare = tomoyo_cred_prepare, | 270 | .cred_prepare = tomoyo_cred_prepare, |
267 | .cred_transfer = tomoyo_cred_transfer, | 271 | .cred_transfer = tomoyo_cred_transfer, |
272 | .cred_free = tomoyo_cred_free, | ||
268 | .bprm_set_creds = tomoyo_bprm_set_creds, | 273 | .bprm_set_creds = tomoyo_bprm_set_creds, |
269 | .bprm_check_security = tomoyo_bprm_check_security, | 274 | .bprm_check_security = tomoyo_bprm_check_security, |
270 | .file_fcntl = tomoyo_file_fcntl, | 275 | .file_fcntl = tomoyo_file_fcntl, |