diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-06-26 10:20:55 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-06-28 19:31:21 -0400 |
commit | 2e503bbb435ae418aebbe4aeede1c6f2a33d6f74 (patch) | |
tree | c6b783c245716cf87b337b2a855e742133afb7ac /security/tomoyo/common.c | |
parent | 5625f2e3266319fd29fe4f1c76ccd3f550c79ac4 (diff) |
TOMOYO: Fix lockdep warning.
Currently TOMOYO holds SRCU lock upon open() and releases it upon close()
because list elements stored in the "struct tomoyo_io_buffer" instances are
accessed until close() is called. However, such SRCU usage causes lockdep to
complain about leaving the kernel with SRCU lock held.
This patch solves the warning by holding/releasing SRCU upon each
read()/write(). This patch is doing something similar to calling kfree()
without calling synchronize_srcu(), by selectively deferring kfree() by keeping
track of the "struct tomoyo_io_buffer" instances.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r-- | security/tomoyo/common.c | 41 |
1 files changed, 14 insertions, 27 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 50481d2cf970..691c34025a4a 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -1820,9 +1820,7 @@ static void tomoyo_read_self_domain(struct tomoyo_io_buffer *head) | |||
1820 | * @type: Type of interface. | 1820 | * @type: Type of interface. |
1821 | * @file: Pointer to "struct file". | 1821 | * @file: Pointer to "struct file". |
1822 | * | 1822 | * |
1823 | * Associates policy handler and returns 0 on success, -ENOMEM otherwise. | 1823 | * Returns 0 on success, negative value otherwise. |
1824 | * | ||
1825 | * Caller acquires tomoyo_read_lock(). | ||
1826 | */ | 1824 | */ |
1827 | int tomoyo_open_control(const u8 type, struct file *file) | 1825 | int tomoyo_open_control(const u8 type, struct file *file) |
1828 | { | 1826 | { |
@@ -1921,9 +1919,6 @@ int tomoyo_open_control(const u8 type, struct file *file) | |||
1921 | return -ENOMEM; | 1919 | return -ENOMEM; |
1922 | } | 1920 | } |
1923 | } | 1921 | } |
1924 | if (type != TOMOYO_QUERY && type != TOMOYO_AUDIT) | ||
1925 | head->reader_idx = tomoyo_read_lock(); | ||
1926 | file->private_data = head; | ||
1927 | /* | 1922 | /* |
1928 | * If the file is /sys/kernel/security/tomoyo/query , increment the | 1923 | * If the file is /sys/kernel/security/tomoyo/query , increment the |
1929 | * observer counter. | 1924 | * observer counter. |
@@ -1932,6 +1927,8 @@ int tomoyo_open_control(const u8 type, struct file *file) | |||
1932 | */ | 1927 | */ |
1933 | if (type == TOMOYO_QUERY) | 1928 | if (type == TOMOYO_QUERY) |
1934 | atomic_inc(&tomoyo_query_observers); | 1929 | atomic_inc(&tomoyo_query_observers); |
1930 | file->private_data = head; | ||
1931 | tomoyo_notify_gc(head, true); | ||
1935 | return 0; | 1932 | return 0; |
1936 | } | 1933 | } |
1937 | 1934 | ||
@@ -2000,13 +1997,12 @@ static inline bool tomoyo_has_more_namespace(struct tomoyo_io_buffer *head) | |||
2000 | * @buffer_len: Size of @buffer. | 1997 | * @buffer_len: Size of @buffer. |
2001 | * | 1998 | * |
2002 | * Returns bytes read on success, negative value otherwise. | 1999 | * Returns bytes read on success, negative value otherwise. |
2003 | * | ||
2004 | * Caller holds tomoyo_read_lock(). | ||
2005 | */ | 2000 | */ |
2006 | int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, | 2001 | int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, |
2007 | const int buffer_len) | 2002 | const int buffer_len) |
2008 | { | 2003 | { |
2009 | int len; | 2004 | int len; |
2005 | int idx; | ||
2010 | 2006 | ||
2011 | if (!head->read) | 2007 | if (!head->read) |
2012 | return -ENOSYS; | 2008 | return -ENOSYS; |
@@ -2014,6 +2010,7 @@ int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, | |||
2014 | return -EINTR; | 2010 | return -EINTR; |
2015 | head->read_user_buf = buffer; | 2011 | head->read_user_buf = buffer; |
2016 | head->read_user_buf_avail = buffer_len; | 2012 | head->read_user_buf_avail = buffer_len; |
2013 | idx = tomoyo_read_lock(); | ||
2017 | if (tomoyo_flush(head)) | 2014 | if (tomoyo_flush(head)) |
2018 | /* Call the policy handler. */ | 2015 | /* Call the policy handler. */ |
2019 | do { | 2016 | do { |
@@ -2021,6 +2018,7 @@ int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, | |||
2021 | head->read(head); | 2018 | head->read(head); |
2022 | } while (tomoyo_flush(head) && | 2019 | } while (tomoyo_flush(head) && |
2023 | tomoyo_has_more_namespace(head)); | 2020 | tomoyo_has_more_namespace(head)); |
2021 | tomoyo_read_unlock(idx); | ||
2024 | len = head->read_user_buf - buffer; | 2022 | len = head->read_user_buf - buffer; |
2025 | mutex_unlock(&head->io_sem); | 2023 | mutex_unlock(&head->io_sem); |
2026 | return len; | 2024 | return len; |
@@ -2071,8 +2069,6 @@ static int tomoyo_parse_policy(struct tomoyo_io_buffer *head, char *line) | |||
2071 | * @buffer_len: Size of @buffer. | 2069 | * @buffer_len: Size of @buffer. |
2072 | * | 2070 | * |
2073 | * Returns @buffer_len on success, negative value otherwise. | 2071 | * Returns @buffer_len on success, negative value otherwise. |
2074 | * | ||
2075 | * Caller holds tomoyo_read_lock(). | ||
2076 | */ | 2072 | */ |
2077 | int tomoyo_write_control(struct tomoyo_io_buffer *head, | 2073 | int tomoyo_write_control(struct tomoyo_io_buffer *head, |
2078 | const char __user *buffer, const int buffer_len) | 2074 | const char __user *buffer, const int buffer_len) |
@@ -2080,12 +2076,14 @@ int tomoyo_write_control(struct tomoyo_io_buffer *head, | |||
2080 | int error = buffer_len; | 2076 | int error = buffer_len; |
2081 | size_t avail_len = buffer_len; | 2077 | size_t avail_len = buffer_len; |
2082 | char *cp0 = head->write_buf; | 2078 | char *cp0 = head->write_buf; |
2079 | int idx; | ||
2083 | if (!head->write) | 2080 | if (!head->write) |
2084 | return -ENOSYS; | 2081 | return -ENOSYS; |
2085 | if (!access_ok(VERIFY_READ, buffer, buffer_len)) | 2082 | if (!access_ok(VERIFY_READ, buffer, buffer_len)) |
2086 | return -EFAULT; | 2083 | return -EFAULT; |
2087 | if (mutex_lock_interruptible(&head->io_sem)) | 2084 | if (mutex_lock_interruptible(&head->io_sem)) |
2088 | return -EINTR; | 2085 | return -EINTR; |
2086 | idx = tomoyo_read_lock(); | ||
2089 | /* Read a line and dispatch it to the policy handler. */ | 2087 | /* Read a line and dispatch it to the policy handler. */ |
2090 | while (avail_len > 0) { | 2088 | while (avail_len > 0) { |
2091 | char c; | 2089 | char c; |
@@ -2148,6 +2146,7 @@ int tomoyo_write_control(struct tomoyo_io_buffer *head, | |||
2148 | } | 2146 | } |
2149 | } | 2147 | } |
2150 | out: | 2148 | out: |
2149 | tomoyo_read_unlock(idx); | ||
2151 | mutex_unlock(&head->io_sem); | 2150 | mutex_unlock(&head->io_sem); |
2152 | return error; | 2151 | return error; |
2153 | } | 2152 | } |
@@ -2157,30 +2156,18 @@ out: | |||
2157 | * | 2156 | * |
2158 | * @head: Pointer to "struct tomoyo_io_buffer". | 2157 | * @head: Pointer to "struct tomoyo_io_buffer". |
2159 | * | 2158 | * |
2160 | * Releases memory and returns 0. | 2159 | * Returns 0. |
2161 | * | ||
2162 | * Caller looses tomoyo_read_lock(). | ||
2163 | */ | 2160 | */ |
2164 | int tomoyo_close_control(struct tomoyo_io_buffer *head) | 2161 | int tomoyo_close_control(struct tomoyo_io_buffer *head) |
2165 | { | 2162 | { |
2166 | const bool is_write = !!head->write_buf; | ||
2167 | |||
2168 | /* | 2163 | /* |
2169 | * If the file is /sys/kernel/security/tomoyo/query , decrement the | 2164 | * If the file is /sys/kernel/security/tomoyo/query , decrement the |
2170 | * observer counter. | 2165 | * observer counter. |
2171 | */ | 2166 | */ |
2172 | if (head->type == TOMOYO_QUERY) | 2167 | if (head->type == TOMOYO_QUERY && |
2173 | atomic_dec(&tomoyo_query_observers); | 2168 | atomic_dec_and_test(&tomoyo_query_observers)) |
2174 | else if (head->type != TOMOYO_AUDIT) | 2169 | wake_up_all(&tomoyo_answer_wait); |
2175 | tomoyo_read_unlock(head->reader_idx); | 2170 | tomoyo_notify_gc(head, false); |
2176 | /* Release memory used for policy I/O. */ | ||
2177 | kfree(head->read_buf); | ||
2178 | head->read_buf = NULL; | ||
2179 | kfree(head->write_buf); | ||
2180 | head->write_buf = NULL; | ||
2181 | kfree(head); | ||
2182 | if (is_write) | ||
2183 | tomoyo_run_gc(); | ||
2184 | return 0; | 2171 | return 0; |
2185 | } | 2172 | } |
2186 | 2173 | ||