diff options
| author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-06-26 10:16:36 -0400 |
|---|---|---|
| committer | James Morris <jmorris@namei.org> | 2011-06-28 19:31:19 -0400 |
| commit | 0df7e8b8f1c25c10820bdc679555f2fbfb897ca0 (patch) | |
| tree | 626a0304fceec0bbee93e43a24bc0f813fe230b7 /security | |
| parent | b5bc60b4ce313b6dbb42e7d32915dcf0a07c2a68 (diff) | |
TOMOYO: Cleanup part 3.
Use common structure for ACL with "struct list_head" + "atomic_t".
Use array/struct where possible.
Remove is_group from "struct tomoyo_name_union"/"struct tomoyo_number_union".
Pass "struct file"->private_data rather than "struct file".
Update some of comments.
Bring tomoyo_same_acl_head() from common.h to domain.c .
Bring tomoyo_invalid()/tomoyo_valid() from common.h to util.c .
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
| -rw-r--r-- | security/tomoyo/common.c | 43 | ||||
| -rw-r--r-- | security/tomoyo/common.h | 78 | ||||
| -rw-r--r-- | security/tomoyo/domain.c | 17 | ||||
| -rw-r--r-- | security/tomoyo/file.c | 208 | ||||
| -rw-r--r-- | security/tomoyo/gc.c | 127 | ||||
| -rw-r--r-- | security/tomoyo/memory.c | 16 | ||||
| -rw-r--r-- | security/tomoyo/mount.c | 31 | ||||
| -rw-r--r-- | security/tomoyo/securityfs_if.c | 6 | ||||
| -rw-r--r-- | security/tomoyo/util.c | 37 |
9 files changed, 410 insertions, 153 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 1c340217a06a..2e6792ded357 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
| @@ -192,7 +192,7 @@ static void tomoyo_print_name_union(struct tomoyo_io_buffer *head, | |||
| 192 | const struct tomoyo_name_union *ptr) | 192 | const struct tomoyo_name_union *ptr) |
| 193 | { | 193 | { |
| 194 | tomoyo_set_space(head); | 194 | tomoyo_set_space(head); |
| 195 | if (ptr->is_group) { | 195 | if (ptr->group) { |
| 196 | tomoyo_set_string(head, "@"); | 196 | tomoyo_set_string(head, "@"); |
| 197 | tomoyo_set_string(head, ptr->group->group_name->name); | 197 | tomoyo_set_string(head, ptr->group->group_name->name); |
| 198 | } else { | 198 | } else { |
| @@ -210,15 +210,15 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, | |||
| 210 | const struct tomoyo_number_union *ptr) | 210 | const struct tomoyo_number_union *ptr) |
| 211 | { | 211 | { |
| 212 | tomoyo_set_space(head); | 212 | tomoyo_set_space(head); |
| 213 | if (ptr->is_group) { | 213 | if (ptr->group) { |
| 214 | tomoyo_set_string(head, "@"); | 214 | tomoyo_set_string(head, "@"); |
| 215 | tomoyo_set_string(head, ptr->group->group_name->name); | 215 | tomoyo_set_string(head, ptr->group->group_name->name); |
| 216 | } else { | 216 | } else { |
| 217 | int i; | 217 | int i; |
| 218 | unsigned long min = ptr->values[0]; | 218 | unsigned long min = ptr->values[0]; |
| 219 | const unsigned long max = ptr->values[1]; | 219 | const unsigned long max = ptr->values[1]; |
| 220 | u8 min_type = ptr->min_type; | 220 | u8 min_type = ptr->value_type[0]; |
| 221 | const u8 max_type = ptr->max_type; | 221 | const u8 max_type = ptr->value_type[1]; |
| 222 | char buffer[128]; | 222 | char buffer[128]; |
| 223 | buffer[0] = '\0'; | 223 | buffer[0] = '\0'; |
| 224 | for (i = 0; i < 2; i++) { | 224 | for (i = 0; i < 2; i++) { |
| @@ -769,7 +769,7 @@ static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data) | |||
| 769 | domain = tomoyo_find_domain(data + 7); | 769 | domain = tomoyo_find_domain(data + 7); |
| 770 | } else | 770 | } else |
| 771 | return false; | 771 | return false; |
| 772 | head->write_var1 = domain; | 772 | head->w.domain = domain; |
| 773 | /* Accessing read_buf is safe because head->io_sem is held. */ | 773 | /* Accessing read_buf is safe because head->io_sem is held. */ |
| 774 | if (!head->read_buf) | 774 | if (!head->read_buf) |
| 775 | return true; /* Do nothing if open(O_WRONLY). */ | 775 | return true; /* Do nothing if open(O_WRONLY). */ |
| @@ -847,7 +847,7 @@ static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain, | |||
| 847 | static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | 847 | static int tomoyo_write_domain(struct tomoyo_io_buffer *head) |
| 848 | { | 848 | { |
| 849 | char *data = head->write_buf; | 849 | char *data = head->write_buf; |
| 850 | struct tomoyo_domain_info *domain = head->write_var1; | 850 | struct tomoyo_domain_info *domain = head->w.domain; |
| 851 | bool is_delete = false; | 851 | bool is_delete = false; |
| 852 | bool is_select = false; | 852 | bool is_select = false; |
| 853 | unsigned int profile; | 853 | unsigned int profile; |
| @@ -869,7 +869,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
| 869 | domain = tomoyo_find_domain(data); | 869 | domain = tomoyo_find_domain(data); |
| 870 | else | 870 | else |
| 871 | domain = tomoyo_assign_domain(data, 0); | 871 | domain = tomoyo_assign_domain(data, 0); |
| 872 | head->write_var1 = domain; | 872 | head->w.domain = domain; |
| 873 | return 0; | 873 | return 0; |
| 874 | } | 874 | } |
| 875 | if (!domain) | 875 | if (!domain) |
| @@ -1250,7 +1250,7 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) | |||
| 1250 | { | 1250 | { |
| 1251 | list_for_each_cookie(head->r.group, &tomoyo_group_list[idx]) { | 1251 | list_for_each_cookie(head->r.group, &tomoyo_group_list[idx]) { |
| 1252 | struct tomoyo_group *group = | 1252 | struct tomoyo_group *group = |
| 1253 | list_entry(head->r.group, typeof(*group), list); | 1253 | list_entry(head->r.group, typeof(*group), head.list); |
| 1254 | list_for_each_cookie(head->r.acl, &group->member_list) { | 1254 | list_for_each_cookie(head->r.acl, &group->member_list) { |
| 1255 | struct tomoyo_acl_head *ptr = | 1255 | struct tomoyo_acl_head *ptr = |
| 1256 | list_entry(head->r.acl, typeof(*ptr), list); | 1256 | list_entry(head->r.acl, typeof(*ptr), list); |
| @@ -1874,7 +1874,7 @@ int tomoyo_poll_control(struct file *file, poll_table *wait) | |||
| 1874 | /** | 1874 | /** |
| 1875 | * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. | 1875 | * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. |
| 1876 | * | 1876 | * |
| 1877 | * @file: Pointer to "struct file". | 1877 | * @head: Pointer to "struct tomoyo_io_buffer". |
| 1878 | * @buffer: Poiner to buffer to write to. | 1878 | * @buffer: Poiner to buffer to write to. |
| 1879 | * @buffer_len: Size of @buffer. | 1879 | * @buffer_len: Size of @buffer. |
| 1880 | * | 1880 | * |
| @@ -1882,11 +1882,10 @@ int tomoyo_poll_control(struct file *file, poll_table *wait) | |||
| 1882 | * | 1882 | * |
| 1883 | * Caller holds tomoyo_read_lock(). | 1883 | * Caller holds tomoyo_read_lock(). |
| 1884 | */ | 1884 | */ |
| 1885 | int tomoyo_read_control(struct file *file, char __user *buffer, | 1885 | int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, |
| 1886 | const int buffer_len) | 1886 | const int buffer_len) |
| 1887 | { | 1887 | { |
| 1888 | int len; | 1888 | int len; |
| 1889 | struct tomoyo_io_buffer *head = file->private_data; | ||
| 1890 | 1889 | ||
| 1891 | if (!head->read) | 1890 | if (!head->read) |
| 1892 | return -ENOSYS; | 1891 | return -ENOSYS; |
| @@ -1906,7 +1905,7 @@ int tomoyo_read_control(struct file *file, char __user *buffer, | |||
| 1906 | /** | 1905 | /** |
| 1907 | * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface. | 1906 | * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface. |
| 1908 | * | 1907 | * |
| 1909 | * @file: Pointer to "struct file". | 1908 | * @head: Pointer to "struct tomoyo_io_buffer". |
| 1910 | * @buffer: Pointer to buffer to read from. | 1909 | * @buffer: Pointer to buffer to read from. |
| 1911 | * @buffer_len: Size of @buffer. | 1910 | * @buffer_len: Size of @buffer. |
| 1912 | * | 1911 | * |
| @@ -1914,10 +1913,9 @@ int tomoyo_read_control(struct file *file, char __user *buffer, | |||
| 1914 | * | 1913 | * |
| 1915 | * Caller holds tomoyo_read_lock(). | 1914 | * Caller holds tomoyo_read_lock(). |
| 1916 | */ | 1915 | */ |
| 1917 | int tomoyo_write_control(struct file *file, const char __user *buffer, | 1916 | int tomoyo_write_control(struct tomoyo_io_buffer *head, |
| 1918 | const int buffer_len) | 1917 | const char __user *buffer, const int buffer_len) |
| 1919 | { | 1918 | { |
| 1920 | struct tomoyo_io_buffer *head = file->private_data; | ||
| 1921 | int error = buffer_len; | 1919 | int error = buffer_len; |
| 1922 | int avail_len = buffer_len; | 1920 | int avail_len = buffer_len; |
| 1923 | char *cp0 = head->write_buf; | 1921 | char *cp0 = head->write_buf; |
| @@ -1935,7 +1933,7 @@ int tomoyo_write_control(struct file *file, const char __user *buffer, | |||
| 1935 | /* Read a line and dispatch it to the policy handler. */ | 1933 | /* Read a line and dispatch it to the policy handler. */ |
| 1936 | while (avail_len > 0) { | 1934 | while (avail_len > 0) { |
| 1937 | char c; | 1935 | char c; |
| 1938 | if (head->write_avail >= head->writebuf_size - 1) { | 1936 | if (head->w.avail >= head->writebuf_size - 1) { |
| 1939 | error = -ENOMEM; | 1937 | error = -ENOMEM; |
| 1940 | break; | 1938 | break; |
| 1941 | } else if (get_user(c, buffer)) { | 1939 | } else if (get_user(c, buffer)) { |
| @@ -1944,11 +1942,11 @@ int tomoyo_write_control(struct file *file, const char __user *buffer, | |||
| 1944 | } | 1942 | } |
| 1945 | buffer++; | 1943 | buffer++; |
| 1946 | avail_len--; | 1944 | avail_len--; |
| 1947 | cp0[head->write_avail++] = c; | 1945 | cp0[head->w.avail++] = c; |
| 1948 | if (c != '\n') | 1946 | if (c != '\n') |
| 1949 | continue; | 1947 | continue; |
| 1950 | cp0[head->write_avail - 1] = '\0'; | 1948 | cp0[head->w.avail - 1] = '\0'; |
| 1951 | head->write_avail = 0; | 1949 | head->w.avail = 0; |
| 1952 | tomoyo_normalize_line(cp0); | 1950 | tomoyo_normalize_line(cp0); |
| 1953 | head->write(head); | 1951 | head->write(head); |
| 1954 | } | 1952 | } |
| @@ -1959,15 +1957,14 @@ int tomoyo_write_control(struct file *file, const char __user *buffer, | |||
| 1959 | /** | 1957 | /** |
| 1960 | * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface. | 1958 | * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface. |
| 1961 | * | 1959 | * |
| 1962 | * @file: Pointer to "struct file". | 1960 | * @head: Pointer to "struct tomoyo_io_buffer". |
| 1963 | * | 1961 | * |
| 1964 | * Releases memory and returns 0. | 1962 | * Releases memory and returns 0. |
| 1965 | * | 1963 | * |
| 1966 | * Caller looses tomoyo_read_lock(). | 1964 | * Caller looses tomoyo_read_lock(). |
| 1967 | */ | 1965 | */ |
| 1968 | int tomoyo_close_control(struct file *file) | 1966 | int tomoyo_close_control(struct tomoyo_io_buffer *head) |
| 1969 | { | 1967 | { |
| 1970 | struct tomoyo_io_buffer *head = file->private_data; | ||
| 1971 | const bool is_write = !!head->write_buf; | 1968 | const bool is_write = !!head->write_buf; |
| 1972 | 1969 | ||
| 1973 | /* | 1970 | /* |
| @@ -1984,8 +1981,6 @@ int tomoyo_close_control(struct file *file) | |||
| 1984 | kfree(head->write_buf); | 1981 | kfree(head->write_buf); |
| 1985 | head->write_buf = NULL; | 1982 | head->write_buf = NULL; |
| 1986 | kfree(head); | 1983 | kfree(head); |
| 1987 | head = NULL; | ||
| 1988 | file->private_data = NULL; | ||
| 1989 | if (is_write) | 1984 | if (is_write) |
| 1990 | tomoyo_run_gc(); | 1985 | tomoyo_run_gc(); |
| 1991 | return 0; | 1986 | return 0; |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index d0645733c102..7aa55eef67bd 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
| @@ -219,6 +219,12 @@ struct tomoyo_acl_head { | |||
| 219 | bool is_deleted; | 219 | bool is_deleted; |
| 220 | } __packed; | 220 | } __packed; |
| 221 | 221 | ||
| 222 | /* Common header for shared entries. */ | ||
| 223 | struct tomoyo_shared_acl_head { | ||
| 224 | struct list_head list; | ||
| 225 | atomic_t users; | ||
| 226 | } __packed; | ||
| 227 | |||
| 222 | /* Structure for request info. */ | 228 | /* Structure for request info. */ |
| 223 | struct tomoyo_request_info { | 229 | struct tomoyo_request_info { |
| 224 | struct tomoyo_domain_info *domain; | 230 | struct tomoyo_domain_info *domain; |
| @@ -281,8 +287,7 @@ struct tomoyo_path_info { | |||
| 281 | 287 | ||
| 282 | /* Structure for holding string data. */ | 288 | /* Structure for holding string data. */ |
| 283 | struct tomoyo_name { | 289 | struct tomoyo_name { |
| 284 | struct list_head list; | 290 | struct tomoyo_shared_acl_head head; |
| 285 | atomic_t users; | ||
| 286 | struct tomoyo_path_info entry; | 291 | struct tomoyo_path_info entry; |
| 287 | }; | 292 | }; |
| 288 | 293 | ||
| @@ -291,8 +296,6 @@ struct tomoyo_name_union { | |||
| 291 | /* Either @filename or @group is NULL. */ | 296 | /* Either @filename or @group is NULL. */ |
| 292 | const struct tomoyo_path_info *filename; | 297 | const struct tomoyo_path_info *filename; |
| 293 | struct tomoyo_group *group; | 298 | struct tomoyo_group *group; |
| 294 | /* True if @group != NULL, false if @filename != NULL. */ | ||
| 295 | u8 is_group; | ||
| 296 | }; | 299 | }; |
| 297 | 300 | ||
| 298 | /* Structure for holding a number. */ | 301 | /* Structure for holding a number. */ |
| @@ -300,18 +303,14 @@ struct tomoyo_number_union { | |||
| 300 | unsigned long values[2]; | 303 | unsigned long values[2]; |
| 301 | struct tomoyo_group *group; /* Maybe NULL. */ | 304 | struct tomoyo_group *group; /* Maybe NULL. */ |
| 302 | /* One of values in "enum tomoyo_value_type". */ | 305 | /* One of values in "enum tomoyo_value_type". */ |
| 303 | u8 min_type; | 306 | u8 value_type[2]; |
| 304 | u8 max_type; | ||
| 305 | /* True if @group != NULL, false otherwise. */ | ||
| 306 | u8 is_group; | ||
| 307 | }; | 307 | }; |
| 308 | 308 | ||
| 309 | /* Structure for "path_group"/"number_group" directive. */ | 309 | /* Structure for "path_group"/"number_group" directive. */ |
| 310 | struct tomoyo_group { | 310 | struct tomoyo_group { |
| 311 | struct list_head list; | 311 | struct tomoyo_shared_acl_head head; |
| 312 | const struct tomoyo_path_info *group_name; | 312 | const struct tomoyo_path_info *group_name; |
| 313 | struct list_head member_list; | 313 | struct list_head member_list; |
| 314 | atomic_t users; | ||
| 315 | }; | 314 | }; |
| 316 | 315 | ||
| 317 | /* Structure for "path_group" directive. */ | 316 | /* Structure for "path_group" directive. */ |
| @@ -429,16 +428,18 @@ struct tomoyo_io_buffer { | |||
| 429 | bool print_execute_only; | 428 | bool print_execute_only; |
| 430 | const char *w[TOMOYO_MAX_IO_READ_QUEUE]; | 429 | const char *w[TOMOYO_MAX_IO_READ_QUEUE]; |
| 431 | } r; | 430 | } r; |
| 432 | /* The position currently writing to. */ | 431 | struct { |
| 433 | struct tomoyo_domain_info *write_var1; | 432 | /* The position currently writing to. */ |
| 433 | struct tomoyo_domain_info *domain; | ||
| 434 | /* Bytes available for writing. */ | ||
| 435 | int avail; | ||
| 436 | } w; | ||
| 434 | /* Buffer for reading. */ | 437 | /* Buffer for reading. */ |
| 435 | char *read_buf; | 438 | char *read_buf; |
| 436 | /* Size of read buffer. */ | 439 | /* Size of read buffer. */ |
| 437 | int readbuf_size; | 440 | int readbuf_size; |
| 438 | /* Buffer for writing. */ | 441 | /* Buffer for writing. */ |
| 439 | char *write_buf; | 442 | char *write_buf; |
| 440 | /* Bytes available for writing. */ | ||
| 441 | int write_avail; | ||
| 442 | /* Size of write buffer. */ | 443 | /* Size of write buffer. */ |
| 443 | int writebuf_size; | 444 | int writebuf_size; |
| 444 | /* Type of this interface. */ | 445 | /* Type of this interface. */ |
| @@ -500,12 +501,12 @@ void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) | |||
| 500 | __attribute__ ((format(printf, 2, 3))); | 501 | __attribute__ ((format(printf, 2, 3))); |
| 501 | void tomoyo_check_profile(void); | 502 | void tomoyo_check_profile(void); |
| 502 | int tomoyo_open_control(const u8 type, struct file *file); | 503 | int tomoyo_open_control(const u8 type, struct file *file); |
| 503 | int tomoyo_close_control(struct file *file); | 504 | int tomoyo_close_control(struct tomoyo_io_buffer *head); |
| 504 | int tomoyo_poll_control(struct file *file, poll_table *wait); | 505 | int tomoyo_poll_control(struct file *file, poll_table *wait); |
| 505 | int tomoyo_read_control(struct file *file, char __user *buffer, | 506 | int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, |
| 506 | const int buffer_len); | 507 | const int buffer_len); |
| 507 | int tomoyo_write_control(struct file *file, const char __user *buffer, | 508 | int tomoyo_write_control(struct tomoyo_io_buffer *head, |
| 508 | const int buffer_len); | 509 | const char __user *buffer, const int buffer_len); |
| 509 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); | 510 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); |
| 510 | void tomoyo_warn_oom(const char *function); | 511 | void tomoyo_warn_oom(const char *function); |
| 511 | const struct tomoyo_path_info * | 512 | const struct tomoyo_path_info * |
| @@ -672,30 +673,6 @@ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, | |||
| 672 | } | 673 | } |
| 673 | 674 | ||
| 674 | /** | 675 | /** |
| 675 | * tomoyo_valid - Check whether the character is a valid char. | ||
| 676 | * | ||
| 677 | * @c: The character to check. | ||
| 678 | * | ||
| 679 | * Returns true if @c is a valid character, false otherwise. | ||
| 680 | */ | ||
| 681 | static inline bool tomoyo_valid(const unsigned char c) | ||
| 682 | { | ||
| 683 | return c > ' ' && c < 127; | ||
| 684 | } | ||
| 685 | |||
| 686 | /** | ||
| 687 | * tomoyo_invalid - Check whether the character is an invalid char. | ||
| 688 | * | ||
| 689 | * @c: The character to check. | ||
| 690 | * | ||
| 691 | * Returns true if @c is an invalid character, false otherwise. | ||
| 692 | */ | ||
| 693 | static inline bool tomoyo_invalid(const unsigned char c) | ||
| 694 | { | ||
| 695 | return c && (c <= ' ' || c >= 127); | ||
| 696 | } | ||
| 697 | |||
| 698 | /** | ||
| 699 | * tomoyo_put_name - Drop reference on "struct tomoyo_name". | 676 | * tomoyo_put_name - Drop reference on "struct tomoyo_name". |
| 700 | * | 677 | * |
| 701 | * @name: Pointer to "struct tomoyo_path_info". Maybe NULL. | 678 | * @name: Pointer to "struct tomoyo_path_info". Maybe NULL. |
| @@ -707,7 +684,7 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name) | |||
| 707 | if (name) { | 684 | if (name) { |
| 708 | struct tomoyo_name *ptr = | 685 | struct tomoyo_name *ptr = |
| 709 | container_of(name, typeof(*ptr), entry); | 686 | container_of(name, typeof(*ptr), entry); |
| 710 | atomic_dec(&ptr->users); | 687 | atomic_dec(&ptr->head.users); |
| 711 | } | 688 | } |
| 712 | } | 689 | } |
| 713 | 690 | ||
| @@ -721,7 +698,7 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name) | |||
| 721 | static inline void tomoyo_put_group(struct tomoyo_group *group) | 698 | static inline void tomoyo_put_group(struct tomoyo_group *group) |
| 722 | { | 699 | { |
| 723 | if (group) | 700 | if (group) |
| 724 | atomic_dec(&group->users); | 701 | atomic_dec(&group->head.users); |
| 725 | } | 702 | } |
| 726 | 703 | ||
| 727 | /** | 704 | /** |
| @@ -747,12 +724,6 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct | |||
| 747 | return task_cred_xxx(task, security); | 724 | return task_cred_xxx(task, security); |
| 748 | } | 725 | } |
| 749 | 726 | ||
| 750 | static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1, | ||
| 751 | const struct tomoyo_acl_info *p2) | ||
| 752 | { | ||
| 753 | return p1->type == p2->type; | ||
| 754 | } | ||
| 755 | |||
| 756 | /** | 727 | /** |
| 757 | * tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry. | 728 | * tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry. |
| 758 | * | 729 | * |
| @@ -764,8 +735,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1, | |||
| 764 | static inline bool tomoyo_same_name_union | 735 | static inline bool tomoyo_same_name_union |
| 765 | (const struct tomoyo_name_union *a, const struct tomoyo_name_union *b) | 736 | (const struct tomoyo_name_union *a, const struct tomoyo_name_union *b) |
| 766 | { | 737 | { |
| 767 | return a->filename == b->filename && a->group == b->group && | 738 | return a->filename == b->filename && a->group == b->group; |
| 768 | a->is_group == b->is_group; | ||
| 769 | } | 739 | } |
| 770 | 740 | ||
| 771 | /** | 741 | /** |
| @@ -780,8 +750,8 @@ static inline bool tomoyo_same_number_union | |||
| 780 | (const struct tomoyo_number_union *a, const struct tomoyo_number_union *b) | 750 | (const struct tomoyo_number_union *a, const struct tomoyo_number_union *b) |
| 781 | { | 751 | { |
| 782 | return a->values[0] == b->values[0] && a->values[1] == b->values[1] && | 752 | return a->values[0] == b->values[0] && a->values[1] == b->values[1] && |
| 783 | a->group == b->group && a->min_type == b->min_type && | 753 | a->group == b->group && a->value_type[0] == b->value_type[0] && |
| 784 | a->max_type == b->max_type && a->is_group == b->is_group; | 754 | a->value_type[1] == b->value_type[1]; |
| 785 | } | 755 | } |
| 786 | 756 | ||
| 787 | /** | 757 | /** |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 355b536262b1..43977083254b 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
| @@ -59,6 +59,20 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, | |||
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | /** | 61 | /** |
| 62 | * tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry. | ||
| 63 | * | ||
| 64 | * @a: Pointer to "struct tomoyo_acl_info". | ||
| 65 | * @b: Pointer to "struct tomoyo_acl_info". | ||
| 66 | * | ||
| 67 | * Returns true if @a == @b, false otherwise. | ||
| 68 | */ | ||
| 69 | static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, | ||
| 70 | const struct tomoyo_acl_info *b) | ||
| 71 | { | ||
| 72 | return a->type == b->type; | ||
| 73 | } | ||
| 74 | |||
| 75 | /** | ||
| 62 | * tomoyo_update_domain - Update an entry for domain policy. | 76 | * tomoyo_update_domain - Update an entry for domain policy. |
| 63 | * | 77 | * |
| 64 | * @new_entry: Pointer to "struct tomoyo_acl_info". | 78 | * @new_entry: Pointer to "struct tomoyo_acl_info". |
| @@ -88,7 +102,8 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, | |||
| 88 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 102 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
| 89 | return error; | 103 | return error; |
| 90 | list_for_each_entry_rcu(entry, &domain->acl_info_list, list) { | 104 | list_for_each_entry_rcu(entry, &domain->acl_info_list, list) { |
| 91 | if (!check_duplicate(entry, new_entry)) | 105 | if (!tomoyo_same_acl_head(entry, new_entry) || |
| 106 | !check_duplicate(entry, new_entry)) | ||
| 92 | continue; | 107 | continue; |
| 93 | if (merge_duplicate) | 108 | if (merge_duplicate) |
| 94 | entry->is_deleted = merge_duplicate(entry, new_entry, | 109 | entry->is_deleted = merge_duplicate(entry, new_entry, |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 332380288078..4259e0a136d8 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
| @@ -49,6 +49,9 @@ const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | |||
| 49 | [TOMOYO_TYPE_CHGRP] = "chgrp", | 49 | [TOMOYO_TYPE_CHGRP] = "chgrp", |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | /* | ||
| 53 | * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index". | ||
| 54 | */ | ||
| 52 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { | 55 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { |
| 53 | [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, | 56 | [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, |
| 54 | [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, | 57 | [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, |
| @@ -63,17 +66,27 @@ static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { | |||
| 63 | [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, | 66 | [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, |
| 64 | }; | 67 | }; |
| 65 | 68 | ||
| 69 | /* | ||
| 70 | * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index". | ||
| 71 | */ | ||
| 66 | static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { | 72 | static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { |
| 67 | [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, | 73 | [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, |
| 68 | [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, | 74 | [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, |
| 69 | }; | 75 | }; |
| 70 | 76 | ||
| 77 | /* | ||
| 78 | * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index". | ||
| 79 | */ | ||
| 71 | static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { | 80 | static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { |
| 72 | [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, | 81 | [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, |
| 73 | [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, | 82 | [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, |
| 74 | [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, | 83 | [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, |
| 75 | }; | 84 | }; |
| 76 | 85 | ||
| 86 | /* | ||
| 87 | * Mapping table from "enum tomoyo_path_number_acl_index" to | ||
| 88 | * "enum tomoyo_mac_index". | ||
| 89 | */ | ||
| 77 | static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | 90 | static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { |
| 78 | [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, | 91 | [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, |
| 79 | [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, | 92 | [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, |
| @@ -85,41 +98,76 @@ static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | |||
| 85 | [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, | 98 | [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, |
| 86 | }; | 99 | }; |
| 87 | 100 | ||
| 101 | /** | ||
| 102 | * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union". | ||
| 103 | * | ||
| 104 | * @ptr: Pointer to "struct tomoyo_name_union". | ||
| 105 | * | ||
| 106 | * Returns nothing. | ||
| 107 | */ | ||
| 88 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) | 108 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) |
| 89 | { | 109 | { |
| 90 | if (!ptr) | 110 | tomoyo_put_group(ptr->group); |
| 91 | return; | 111 | tomoyo_put_name(ptr->filename); |
| 92 | if (ptr->is_group) | ||
| 93 | tomoyo_put_group(ptr->group); | ||
| 94 | else | ||
| 95 | tomoyo_put_name(ptr->filename); | ||
| 96 | } | 112 | } |
| 97 | 113 | ||
| 114 | /** | ||
| 115 | * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not. | ||
| 116 | * | ||
| 117 | * @name: Pointer to "struct tomoyo_path_info". | ||
| 118 | * @ptr: Pointer to "struct tomoyo_name_union". | ||
| 119 | * | ||
| 120 | * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise. | ||
| 121 | */ | ||
| 98 | const struct tomoyo_path_info * | 122 | const struct tomoyo_path_info * |
| 99 | tomoyo_compare_name_union(const struct tomoyo_path_info *name, | 123 | tomoyo_compare_name_union(const struct tomoyo_path_info *name, |
| 100 | const struct tomoyo_name_union *ptr) | 124 | const struct tomoyo_name_union *ptr) |
| 101 | { | 125 | { |
| 102 | if (ptr->is_group) | 126 | if (ptr->group) |
| 103 | return tomoyo_path_matches_group(name, ptr->group); | 127 | return tomoyo_path_matches_group(name, ptr->group); |
| 104 | if (tomoyo_path_matches_pattern(name, ptr->filename)) | 128 | if (tomoyo_path_matches_pattern(name, ptr->filename)) |
| 105 | return ptr->filename; | 129 | return ptr->filename; |
| 106 | return NULL; | 130 | return NULL; |
| 107 | } | 131 | } |
| 108 | 132 | ||
| 133 | /** | ||
| 134 | * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union". | ||
| 135 | * | ||
| 136 | * @ptr: Pointer to "struct tomoyo_number_union". | ||
| 137 | * | ||
| 138 | * Returns nothing. | ||
| 139 | */ | ||
| 109 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr) | 140 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr) |
| 110 | { | 141 | { |
| 111 | if (ptr && ptr->is_group) | 142 | tomoyo_put_group(ptr->group); |
| 112 | tomoyo_put_group(ptr->group); | ||
| 113 | } | 143 | } |
| 114 | 144 | ||
| 145 | /** | ||
| 146 | * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not. | ||
| 147 | * | ||
| 148 | * @value: Number to check. | ||
| 149 | * @ptr: Pointer to "struct tomoyo_number_union". | ||
| 150 | * | ||
| 151 | * Returns true if @value matches @ptr, false otherwise. | ||
| 152 | */ | ||
| 115 | bool tomoyo_compare_number_union(const unsigned long value, | 153 | bool tomoyo_compare_number_union(const unsigned long value, |
| 116 | const struct tomoyo_number_union *ptr) | 154 | const struct tomoyo_number_union *ptr) |
| 117 | { | 155 | { |
| 118 | if (ptr->is_group) | 156 | if (ptr->group) |
| 119 | return tomoyo_number_matches_group(value, value, ptr->group); | 157 | return tomoyo_number_matches_group(value, value, ptr->group); |
| 120 | return value >= ptr->values[0] && value <= ptr->values[1]; | 158 | return value >= ptr->values[0] && value <= ptr->values[1]; |
| 121 | } | 159 | } |
| 122 | 160 | ||
| 161 | /** | ||
| 162 | * tomoyo_add_slash - Add trailing '/' if needed. | ||
| 163 | * | ||
| 164 | * @buf: Pointer to "struct tomoyo_path_info". | ||
| 165 | * | ||
| 166 | * Returns nothing. | ||
| 167 | * | ||
| 168 | * @buf must be generated by tomoyo_encode() because this function does not | ||
| 169 | * allocate memory for adding '/'. | ||
| 170 | */ | ||
| 123 | static void tomoyo_add_slash(struct tomoyo_path_info *buf) | 171 | static void tomoyo_add_slash(struct tomoyo_path_info *buf) |
| 124 | { | 172 | { |
| 125 | if (buf->is_dir) | 173 | if (buf->is_dir) |
| @@ -247,6 +295,18 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) | |||
| 247 | filename->name, buffer); | 295 | filename->name, buffer); |
| 248 | } | 296 | } |
| 249 | 297 | ||
| 298 | /** | ||
| 299 | * tomoyo_check_path_acl - Check permission for path operation. | ||
| 300 | * | ||
| 301 | * @r: Pointer to "struct tomoyo_request_info". | ||
| 302 | * @ptr: Pointer to "struct tomoyo_acl_info". | ||
| 303 | * | ||
| 304 | * Returns true if granted, false otherwise. | ||
| 305 | * | ||
| 306 | * To be able to use wildcard for domain transition, this function sets | ||
| 307 | * matching entry on success. Since the caller holds tomoyo_read_lock(), | ||
| 308 | * it is safe to set matching entry. | ||
| 309 | */ | ||
| 250 | static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, | 310 | static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, |
| 251 | const struct tomoyo_acl_info *ptr) | 311 | const struct tomoyo_acl_info *ptr) |
| 252 | { | 312 | { |
| @@ -261,6 +321,14 @@ static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, | |||
| 261 | return false; | 321 | return false; |
| 262 | } | 322 | } |
| 263 | 323 | ||
| 324 | /** | ||
| 325 | * tomoyo_check_path_number_acl - Check permission for path number operation. | ||
| 326 | * | ||
| 327 | * @r: Pointer to "struct tomoyo_request_info". | ||
| 328 | * @ptr: Pointer to "struct tomoyo_acl_info". | ||
| 329 | * | ||
| 330 | * Returns true if granted, false otherwise. | ||
| 331 | */ | ||
| 264 | static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, | 332 | static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, |
| 265 | const struct tomoyo_acl_info *ptr) | 333 | const struct tomoyo_acl_info *ptr) |
| 266 | { | 334 | { |
| @@ -273,6 +341,14 @@ static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, | |||
| 273 | &acl->name); | 341 | &acl->name); |
| 274 | } | 342 | } |
| 275 | 343 | ||
| 344 | /** | ||
| 345 | * tomoyo_check_path2_acl - Check permission for path path operation. | ||
| 346 | * | ||
| 347 | * @r: Pointer to "struct tomoyo_request_info". | ||
| 348 | * @ptr: Pointer to "struct tomoyo_acl_info". | ||
| 349 | * | ||
| 350 | * Returns true if granted, false otherwise. | ||
| 351 | */ | ||
| 276 | static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, | 352 | static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, |
| 277 | const struct tomoyo_acl_info *ptr) | 353 | const struct tomoyo_acl_info *ptr) |
| 278 | { | 354 | { |
| @@ -284,8 +360,16 @@ static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, | |||
| 284 | &acl->name2); | 360 | &acl->name2); |
| 285 | } | 361 | } |
| 286 | 362 | ||
| 363 | /** | ||
| 364 | * tomoyo_check_mkdev_acl - Check permission for path number number number operation. | ||
| 365 | * | ||
| 366 | * @r: Pointer to "struct tomoyo_request_info". | ||
| 367 | * @ptr: Pointer to "struct tomoyo_acl_info". | ||
| 368 | * | ||
| 369 | * Returns true if granted, false otherwise. | ||
| 370 | */ | ||
| 287 | static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, | 371 | static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, |
| 288 | const struct tomoyo_acl_info *ptr) | 372 | const struct tomoyo_acl_info *ptr) |
| 289 | { | 373 | { |
| 290 | const struct tomoyo_mkdev_acl *acl = | 374 | const struct tomoyo_mkdev_acl *acl = |
| 291 | container_of(ptr, typeof(*acl), head); | 375 | container_of(ptr, typeof(*acl), head); |
| @@ -300,13 +384,20 @@ static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, | |||
| 300 | &acl->name); | 384 | &acl->name); |
| 301 | } | 385 | } |
| 302 | 386 | ||
| 387 | /** | ||
| 388 | * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry. | ||
| 389 | * | ||
| 390 | * @a: Pointer to "struct tomoyo_acl_info". | ||
| 391 | * @b: Pointer to "struct tomoyo_acl_info". | ||
| 392 | * | ||
| 393 | * Returns true if @a == @b except permission bits, false otherwise. | ||
| 394 | */ | ||
| 303 | static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, | 395 | static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, |
| 304 | const struct tomoyo_acl_info *b) | 396 | const struct tomoyo_acl_info *b) |
| 305 | { | 397 | { |
| 306 | const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); | 398 | const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); |
| 307 | const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); | 399 | const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); |
| 308 | return tomoyo_same_acl_head(&p1->head, &p2->head) && | 400 | return tomoyo_same_name_union(&p1->name, &p2->name); |
| 309 | tomoyo_same_name_union(&p1->name, &p2->name); | ||
| 310 | } | 401 | } |
| 311 | 402 | ||
| 312 | /** | 403 | /** |
| @@ -364,23 +455,37 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, | |||
| 364 | return error; | 455 | return error; |
| 365 | } | 456 | } |
| 366 | 457 | ||
| 458 | /** | ||
| 459 | * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry. | ||
| 460 | * | ||
| 461 | * @a: Pointer to "struct tomoyo_acl_info". | ||
| 462 | * @b: Pointer to "struct tomoyo_acl_info". | ||
| 463 | * | ||
| 464 | * Returns true if @a == @b except permission bits, false otherwise. | ||
| 465 | */ | ||
| 367 | static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, | 466 | static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, |
| 368 | const struct tomoyo_acl_info *b) | 467 | const struct tomoyo_acl_info *b) |
| 369 | { | 468 | { |
| 370 | const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), | 469 | const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head); |
| 371 | head); | 470 | const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head); |
| 372 | const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), | 471 | return tomoyo_same_name_union(&p1->name, &p2->name) && |
| 373 | head); | 472 | tomoyo_same_number_union(&p1->mode, &p2->mode) && |
| 374 | return tomoyo_same_acl_head(&p1->head, &p2->head) | 473 | tomoyo_same_number_union(&p1->major, &p2->major) && |
| 375 | && tomoyo_same_name_union(&p1->name, &p2->name) | 474 | tomoyo_same_number_union(&p1->minor, &p2->minor); |
| 376 | && tomoyo_same_number_union(&p1->mode, &p2->mode) | ||
| 377 | && tomoyo_same_number_union(&p1->major, &p2->major) | ||
| 378 | && tomoyo_same_number_union(&p1->minor, &p2->minor); | ||
| 379 | } | 475 | } |
| 380 | 476 | ||
| 477 | /** | ||
| 478 | * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry. | ||
| 479 | * | ||
| 480 | * @a: Pointer to "struct tomoyo_acl_info". | ||
| 481 | * @b: Pointer to "struct tomoyo_acl_info". | ||
| 482 | * @is_delete: True for @a &= ~@b, false for @a |= @b. | ||
| 483 | * | ||
| 484 | * Returns true if @a is empty, false otherwise. | ||
| 485 | */ | ||
| 381 | static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, | 486 | static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, |
| 382 | struct tomoyo_acl_info *b, | 487 | struct tomoyo_acl_info *b, |
| 383 | const bool is_delete) | 488 | const bool is_delete) |
| 384 | { | 489 | { |
| 385 | u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, | 490 | u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, |
| 386 | head)->perm; | 491 | head)->perm; |
| @@ -411,9 +516,9 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, | |||
| 411 | * Caller holds tomoyo_read_lock(). | 516 | * Caller holds tomoyo_read_lock(). |
| 412 | */ | 517 | */ |
| 413 | static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, | 518 | static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, |
| 414 | char *mode, char *major, char *minor, | 519 | char *mode, char *major, char *minor, |
| 415 | struct tomoyo_domain_info * const | 520 | struct tomoyo_domain_info * const domain, |
| 416 | domain, const bool is_delete) | 521 | const bool is_delete) |
| 417 | { | 522 | { |
| 418 | struct tomoyo_mkdev_acl e = { | 523 | struct tomoyo_mkdev_acl e = { |
| 419 | .head.type = TOMOYO_TYPE_MKDEV_ACL, | 524 | .head.type = TOMOYO_TYPE_MKDEV_ACL, |
| @@ -436,16 +541,32 @@ static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, | |||
| 436 | return error; | 541 | return error; |
| 437 | } | 542 | } |
| 438 | 543 | ||
| 544 | /** | ||
| 545 | * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry. | ||
| 546 | * | ||
| 547 | * @a: Pointer to "struct tomoyo_acl_info". | ||
| 548 | * @b: Pointer to "struct tomoyo_acl_info". | ||
| 549 | * | ||
| 550 | * Returns true if @a == @b except permission bits, false otherwise. | ||
| 551 | */ | ||
| 439 | static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, | 552 | static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, |
| 440 | const struct tomoyo_acl_info *b) | 553 | const struct tomoyo_acl_info *b) |
| 441 | { | 554 | { |
| 442 | const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); | 555 | const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); |
| 443 | const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); | 556 | const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); |
| 444 | return tomoyo_same_acl_head(&p1->head, &p2->head) | 557 | return tomoyo_same_name_union(&p1->name1, &p2->name1) && |
| 445 | && tomoyo_same_name_union(&p1->name1, &p2->name1) | 558 | tomoyo_same_name_union(&p1->name2, &p2->name2); |
| 446 | && tomoyo_same_name_union(&p1->name2, &p2->name2); | ||
| 447 | } | 559 | } |
| 448 | 560 | ||
| 561 | /** | ||
| 562 | * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry. | ||
| 563 | * | ||
| 564 | * @a: Pointer to "struct tomoyo_acl_info". | ||
| 565 | * @b: Pointer to "struct tomoyo_acl_info". | ||
| 566 | * @is_delete: True for @a &= ~@b, false for @a |= @b. | ||
| 567 | * | ||
| 568 | * Returns true if @a is empty, false otherwise. | ||
| 569 | */ | ||
| 449 | static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, | 570 | static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, |
| 450 | struct tomoyo_acl_info *b, | 571 | struct tomoyo_acl_info *b, |
| 451 | const bool is_delete) | 572 | const bool is_delete) |
| @@ -532,6 +653,14 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |||
| 532 | return error; | 653 | return error; |
| 533 | } | 654 | } |
| 534 | 655 | ||
| 656 | /** | ||
| 657 | * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry. | ||
| 658 | * | ||
| 659 | * @a: Pointer to "struct tomoyo_acl_info". | ||
| 660 | * @b: Pointer to "struct tomoyo_acl_info". | ||
| 661 | * | ||
| 662 | * Returns true if @a == @b except permission bits, false otherwise. | ||
| 663 | */ | ||
| 535 | static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, | 664 | static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, |
| 536 | const struct tomoyo_acl_info *b) | 665 | const struct tomoyo_acl_info *b) |
| 537 | { | 666 | { |
| @@ -539,11 +668,19 @@ static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, | |||
| 539 | head); | 668 | head); |
| 540 | const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), | 669 | const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), |
| 541 | head); | 670 | head); |
| 542 | return tomoyo_same_acl_head(&p1->head, &p2->head) | 671 | return tomoyo_same_name_union(&p1->name, &p2->name) && |
| 543 | && tomoyo_same_name_union(&p1->name, &p2->name) | 672 | tomoyo_same_number_union(&p1->number, &p2->number); |
| 544 | && tomoyo_same_number_union(&p1->number, &p2->number); | ||
| 545 | } | 673 | } |
| 546 | 674 | ||
| 675 | /** | ||
| 676 | * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry. | ||
| 677 | * | ||
| 678 | * @a: Pointer to "struct tomoyo_acl_info". | ||
| 679 | * @b: Pointer to "struct tomoyo_acl_info". | ||
| 680 | * @is_delete: True for @a &= ~@b, false for @a |= @b. | ||
| 681 | * | ||
| 682 | * Returns true if @a is empty, false otherwise. | ||
| 683 | */ | ||
| 547 | static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, | 684 | static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, |
| 548 | struct tomoyo_acl_info *b, | 685 | struct tomoyo_acl_info *b, |
| 549 | const bool is_delete) | 686 | const bool is_delete) |
| @@ -575,8 +712,7 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, | |||
| 575 | static int tomoyo_update_path_number_acl(const u8 type, const char *filename, | 712 | static int tomoyo_update_path_number_acl(const u8 type, const char *filename, |
| 576 | char *number, | 713 | char *number, |
| 577 | struct tomoyo_domain_info * const | 714 | struct tomoyo_domain_info * const |
| 578 | domain, | 715 | domain, const bool is_delete) |
| 579 | const bool is_delete) | ||
| 580 | { | 716 | { |
| 581 | struct tomoyo_path_number_acl e = { | 717 | struct tomoyo_path_number_acl e = { |
| 582 | .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, | 718 | .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, |
| @@ -737,7 +873,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
| 737 | * Returns 0 on success, negative value otherwise. | 873 | * Returns 0 on success, negative value otherwise. |
| 738 | */ | 874 | */ |
| 739 | int tomoyo_mkdev_perm(const u8 operation, struct path *path, | 875 | int tomoyo_mkdev_perm(const u8 operation, struct path *path, |
| 740 | const unsigned int mode, unsigned int dev) | 876 | const unsigned int mode, unsigned int dev) |
| 741 | { | 877 | { |
| 742 | struct tomoyo_request_info r; | 878 | struct tomoyo_request_info r; |
| 743 | int error = -ENOMEM; | 879 | int error = -ENOMEM; |
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index ba799b49ee3a..de14030823cd 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
| @@ -13,13 +13,30 @@ | |||
| 13 | 13 | ||
| 14 | struct tomoyo_gc { | 14 | struct tomoyo_gc { |
| 15 | struct list_head list; | 15 | struct list_head list; |
| 16 | int type; | 16 | enum tomoyo_policy_id type; |
| 17 | struct list_head *element; | 17 | struct list_head *element; |
| 18 | }; | 18 | }; |
| 19 | static LIST_HEAD(tomoyo_gc_queue); | 19 | static LIST_HEAD(tomoyo_gc_queue); |
| 20 | static DEFINE_MUTEX(tomoyo_gc_mutex); | 20 | static DEFINE_MUTEX(tomoyo_gc_mutex); |
| 21 | 21 | ||
| 22 | /* Caller holds tomoyo_policy_lock mutex. */ | 22 | /** |
| 23 | * tomoyo_add_to_gc - Add an entry to to be deleted list. | ||
| 24 | * | ||
| 25 | * @type: One of values in "enum tomoyo_policy_id". | ||
| 26 | * @element: Pointer to "struct list_head". | ||
| 27 | * | ||
| 28 | * Returns true on success, false otherwise. | ||
| 29 | * | ||
| 30 | * Caller holds tomoyo_policy_lock mutex. | ||
| 31 | * | ||
| 32 | * Adding an entry needs kmalloc(). Thus, if we try to add thousands of | ||
| 33 | * entries at once, it will take too long time. Thus, do not add more than 128 | ||
| 34 | * entries per a scan. But to be able to handle worst case where all entries | ||
| 35 | * are in-use, we accept one more entry per a scan. | ||
| 36 | * | ||
| 37 | * If we use singly linked list using "struct list_head"->prev (which is | ||
| 38 | * LIST_POISON2), we can avoid kmalloc(). | ||
| 39 | */ | ||
| 23 | static bool tomoyo_add_to_gc(const int type, struct list_head *element) | 40 | static bool tomoyo_add_to_gc(const int type, struct list_head *element) |
| 24 | { | 41 | { |
| 25 | struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | 42 | struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); |
| @@ -32,6 +49,13 @@ static bool tomoyo_add_to_gc(const int type, struct list_head *element) | |||
| 32 | return true; | 49 | return true; |
| 33 | } | 50 | } |
| 34 | 51 | ||
| 52 | /** | ||
| 53 | * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control". | ||
| 54 | * | ||
| 55 | * @element: Pointer to "struct list_head". | ||
| 56 | * | ||
| 57 | * Returns nothing. | ||
| 58 | */ | ||
| 35 | static void tomoyo_del_transition_control(struct list_head *element) | 59 | static void tomoyo_del_transition_control(struct list_head *element) |
| 36 | { | 60 | { |
| 37 | struct tomoyo_transition_control *ptr = | 61 | struct tomoyo_transition_control *ptr = |
| @@ -40,6 +64,13 @@ static void tomoyo_del_transition_control(struct list_head *element) | |||
| 40 | tomoyo_put_name(ptr->program); | 64 | tomoyo_put_name(ptr->program); |
| 41 | } | 65 | } |
| 42 | 66 | ||
| 67 | /** | ||
| 68 | * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator". | ||
| 69 | * | ||
| 70 | * @element: Pointer to "struct list_head". | ||
| 71 | * | ||
| 72 | * Returns nothing. | ||
| 73 | */ | ||
| 43 | static void tomoyo_del_aggregator(struct list_head *element) | 74 | static void tomoyo_del_aggregator(struct list_head *element) |
| 44 | { | 75 | { |
| 45 | struct tomoyo_aggregator *ptr = | 76 | struct tomoyo_aggregator *ptr = |
| @@ -48,6 +79,13 @@ static void tomoyo_del_aggregator(struct list_head *element) | |||
| 48 | tomoyo_put_name(ptr->aggregated_name); | 79 | tomoyo_put_name(ptr->aggregated_name); |
| 49 | } | 80 | } |
| 50 | 81 | ||
| 82 | /** | ||
| 83 | * tomoyo_del_manager - Delete members in "struct tomoyo_manager". | ||
| 84 | * | ||
| 85 | * @element: Pointer to "struct list_head". | ||
| 86 | * | ||
| 87 | * Returns nothing. | ||
| 88 | */ | ||
| 51 | static void tomoyo_del_manager(struct list_head *element) | 89 | static void tomoyo_del_manager(struct list_head *element) |
| 52 | { | 90 | { |
| 53 | struct tomoyo_manager *ptr = | 91 | struct tomoyo_manager *ptr = |
| @@ -55,6 +93,13 @@ static void tomoyo_del_manager(struct list_head *element) | |||
| 55 | tomoyo_put_name(ptr->manager); | 93 | tomoyo_put_name(ptr->manager); |
| 56 | } | 94 | } |
| 57 | 95 | ||
| 96 | /** | ||
| 97 | * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info". | ||
| 98 | * | ||
| 99 | * @element: Pointer to "struct list_head". | ||
| 100 | * | ||
| 101 | * Returns nothing. | ||
| 102 | */ | ||
| 58 | static void tomoyo_del_acl(struct list_head *element) | 103 | static void tomoyo_del_acl(struct list_head *element) |
| 59 | { | 104 | { |
| 60 | struct tomoyo_acl_info *acl = | 105 | struct tomoyo_acl_info *acl = |
| @@ -145,12 +190,26 @@ static bool tomoyo_del_domain(struct list_head *element) | |||
| 145 | } | 190 | } |
| 146 | 191 | ||
| 147 | 192 | ||
| 193 | /** | ||
| 194 | * tomoyo_del_name - Delete members in "struct tomoyo_name". | ||
| 195 | * | ||
| 196 | * @element: Pointer to "struct list_head". | ||
| 197 | * | ||
| 198 | * Returns nothing. | ||
| 199 | */ | ||
| 148 | static void tomoyo_del_name(struct list_head *element) | 200 | static void tomoyo_del_name(struct list_head *element) |
| 149 | { | 201 | { |
| 150 | const struct tomoyo_name *ptr = | 202 | const struct tomoyo_name *ptr = |
| 151 | container_of(element, typeof(*ptr), list); | 203 | container_of(element, typeof(*ptr), head.list); |
| 152 | } | 204 | } |
| 153 | 205 | ||
| 206 | /** | ||
| 207 | * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group". | ||
| 208 | * | ||
| 209 | * @element: Pointer to "struct list_head". | ||
| 210 | * | ||
| 211 | * Returns nothing. | ||
| 212 | */ | ||
| 154 | static void tomoyo_del_path_group(struct list_head *element) | 213 | static void tomoyo_del_path_group(struct list_head *element) |
| 155 | { | 214 | { |
| 156 | struct tomoyo_path_group *member = | 215 | struct tomoyo_path_group *member = |
| @@ -158,20 +217,43 @@ static void tomoyo_del_path_group(struct list_head *element) | |||
| 158 | tomoyo_put_name(member->member_name); | 217 | tomoyo_put_name(member->member_name); |
| 159 | } | 218 | } |
| 160 | 219 | ||
| 220 | /** | ||
| 221 | * tomoyo_del_group - Delete "struct tomoyo_group". | ||
| 222 | * | ||
| 223 | * @element: Pointer to "struct list_head". | ||
| 224 | * | ||
| 225 | * Returns nothing. | ||
| 226 | */ | ||
| 161 | static void tomoyo_del_group(struct list_head *element) | 227 | static void tomoyo_del_group(struct list_head *element) |
| 162 | { | 228 | { |
| 163 | struct tomoyo_group *group = | 229 | struct tomoyo_group *group = |
| 164 | container_of(element, typeof(*group), list); | 230 | container_of(element, typeof(*group), head.list); |
| 165 | tomoyo_put_name(group->group_name); | 231 | tomoyo_put_name(group->group_name); |
| 166 | } | 232 | } |
| 167 | 233 | ||
| 234 | /** | ||
| 235 | * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group". | ||
| 236 | * | ||
| 237 | * @element: Pointer to "struct list_head". | ||
| 238 | * | ||
| 239 | * Returns nothing. | ||
| 240 | */ | ||
| 168 | static void tomoyo_del_number_group(struct list_head *element) | 241 | static void tomoyo_del_number_group(struct list_head *element) |
| 169 | { | 242 | { |
| 170 | struct tomoyo_number_group *member = | 243 | struct tomoyo_number_group *member = |
| 171 | container_of(element, typeof(*member), head.list); | 244 | container_of(element, typeof(*member), head.list); |
| 172 | } | 245 | } |
| 173 | 246 | ||
| 174 | static bool tomoyo_collect_member(struct list_head *member_list, int id) | 247 | /** |
| 248 | * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head". | ||
| 249 | * | ||
| 250 | * @id: One of values in "enum tomoyo_policy_id". | ||
| 251 | * @member_list: Pointer to "struct list_head". | ||
| 252 | * | ||
| 253 | * Returns true if some elements are deleted, false otherwise. | ||
| 254 | */ | ||
| 255 | static bool tomoyo_collect_member(const enum tomoyo_policy_id id, | ||
| 256 | struct list_head *member_list) | ||
| 175 | { | 257 | { |
| 176 | struct tomoyo_acl_head *member; | 258 | struct tomoyo_acl_head *member; |
| 177 | list_for_each_entry(member, member_list, list) { | 259 | list_for_each_entry(member, member_list, list) { |
| @@ -195,13 +277,18 @@ static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain) | |||
| 195 | return true; | 277 | return true; |
| 196 | } | 278 | } |
| 197 | 279 | ||
| 280 | /** | ||
| 281 | * tomoyo_collect_entry - Scan lists for deleted elements. | ||
| 282 | * | ||
| 283 | * Returns nothing. | ||
| 284 | */ | ||
| 198 | static void tomoyo_collect_entry(void) | 285 | static void tomoyo_collect_entry(void) |
| 199 | { | 286 | { |
| 200 | int i; | 287 | int i; |
| 201 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 288 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
| 202 | return; | 289 | return; |
| 203 | for (i = 0; i < TOMOYO_MAX_POLICY; i++) { | 290 | for (i = 0; i < TOMOYO_MAX_POLICY; i++) { |
| 204 | if (!tomoyo_collect_member(&tomoyo_policy_list[i], i)) | 291 | if (!tomoyo_collect_member(i, &tomoyo_policy_list[i])) |
| 205 | goto unlock; | 292 | goto unlock; |
| 206 | } | 293 | } |
| 207 | { | 294 | { |
| @@ -222,10 +309,10 @@ static void tomoyo_collect_entry(void) | |||
| 222 | } | 309 | } |
| 223 | for (i = 0; i < TOMOYO_MAX_HASH; i++) { | 310 | for (i = 0; i < TOMOYO_MAX_HASH; i++) { |
| 224 | struct tomoyo_name *ptr; | 311 | struct tomoyo_name *ptr; |
| 225 | list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], list) { | 312 | list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], head.list) { |
| 226 | if (atomic_read(&ptr->users)) | 313 | if (atomic_read(&ptr->head.users)) |
| 227 | continue; | 314 | continue; |
| 228 | if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list)) | 315 | if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->head.list)) |
| 229 | goto unlock; | 316 | goto unlock; |
| 230 | } | 317 | } |
| 231 | } | 318 | } |
| @@ -241,13 +328,14 @@ static void tomoyo_collect_entry(void) | |||
| 241 | id = TOMOYO_ID_NUMBER_GROUP; | 328 | id = TOMOYO_ID_NUMBER_GROUP; |
| 242 | break; | 329 | break; |
| 243 | } | 330 | } |
| 244 | list_for_each_entry(group, list, list) { | 331 | list_for_each_entry(group, list, head.list) { |
| 245 | if (!tomoyo_collect_member(&group->member_list, id)) | 332 | if (!tomoyo_collect_member(id, &group->member_list)) |
| 246 | goto unlock; | 333 | goto unlock; |
| 247 | if (!list_empty(&group->member_list) || | 334 | if (!list_empty(&group->member_list) || |
| 248 | atomic_read(&group->users)) | 335 | atomic_read(&group->head.users)) |
| 249 | continue; | 336 | continue; |
| 250 | if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list)) | 337 | if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, |
| 338 | &group->head.list)) | ||
| 251 | goto unlock; | 339 | goto unlock; |
| 252 | } | 340 | } |
| 253 | } | 341 | } |
| @@ -291,6 +379,8 @@ static void tomoyo_kfree_entry(void) | |||
| 291 | case TOMOYO_ID_NUMBER_GROUP: | 379 | case TOMOYO_ID_NUMBER_GROUP: |
| 292 | tomoyo_del_number_group(element); | 380 | tomoyo_del_number_group(element); |
| 293 | break; | 381 | break; |
| 382 | case TOMOYO_MAX_POLICY: | ||
| 383 | break; | ||
| 294 | } | 384 | } |
| 295 | tomoyo_memory_free(element); | 385 | tomoyo_memory_free(element); |
| 296 | list_del(&p->list); | 386 | list_del(&p->list); |
| @@ -298,6 +388,17 @@ static void tomoyo_kfree_entry(void) | |||
| 298 | } | 388 | } |
| 299 | } | 389 | } |
| 300 | 390 | ||
| 391 | /** | ||
| 392 | * tomoyo_gc_thread - Garbage collector thread function. | ||
| 393 | * | ||
| 394 | * @unused: Unused. | ||
| 395 | * | ||
| 396 | * In case OOM-killer choose this thread for termination, we create this thread | ||
| 397 | * as a short live thread whenever /sys/kernel/security/tomoyo/ interface was | ||
| 398 | * close()d. | ||
| 399 | * | ||
| 400 | * Returns 0. | ||
| 401 | */ | ||
| 301 | static int tomoyo_gc_thread(void *unused) | 402 | static int tomoyo_gc_thread(void *unused) |
| 302 | { | 403 | { |
| 303 | daemonize("GC for TOMOYO"); | 404 | daemonize("GC for TOMOYO"); |
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 42a7b1ba8cbf..dfef0cb268dc 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c | |||
| @@ -110,10 +110,10 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) | |||
| 110 | return NULL; | 110 | return NULL; |
| 111 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 111 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
| 112 | goto out; | 112 | goto out; |
| 113 | list_for_each_entry(group, &tomoyo_group_list[idx], list) { | 113 | list_for_each_entry(group, &tomoyo_group_list[idx], head.list) { |
| 114 | if (e.group_name != group->group_name) | 114 | if (e.group_name != group->group_name) |
| 115 | continue; | 115 | continue; |
| 116 | atomic_inc(&group->users); | 116 | atomic_inc(&group->head.users); |
| 117 | found = true; | 117 | found = true; |
| 118 | break; | 118 | break; |
| 119 | } | 119 | } |
| @@ -121,8 +121,8 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) | |||
| 121 | struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); | 121 | struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); |
| 122 | if (entry) { | 122 | if (entry) { |
| 123 | INIT_LIST_HEAD(&entry->member_list); | 123 | INIT_LIST_HEAD(&entry->member_list); |
| 124 | atomic_set(&entry->users, 1); | 124 | atomic_set(&entry->head.users, 1); |
| 125 | list_add_tail_rcu(&entry->list, | 125 | list_add_tail_rcu(&entry->head.list, |
| 126 | &tomoyo_group_list[idx]); | 126 | &tomoyo_group_list[idx]); |
| 127 | group = entry; | 127 | group = entry; |
| 128 | found = true; | 128 | found = true; |
| @@ -164,10 +164,10 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) | |||
| 164 | head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; | 164 | head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; |
| 165 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 165 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
| 166 | return NULL; | 166 | return NULL; |
| 167 | list_for_each_entry(ptr, head, list) { | 167 | list_for_each_entry(ptr, head, head.list) { |
| 168 | if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) | 168 | if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) |
| 169 | continue; | 169 | continue; |
| 170 | atomic_inc(&ptr->users); | 170 | atomic_inc(&ptr->head.users); |
| 171 | goto out; | 171 | goto out; |
| 172 | } | 172 | } |
| 173 | ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); | 173 | ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); |
| @@ -183,9 +183,9 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) | |||
| 183 | atomic_add(allocated_len, &tomoyo_policy_memory_size); | 183 | atomic_add(allocated_len, &tomoyo_policy_memory_size); |
| 184 | ptr->entry.name = ((char *) ptr) + sizeof(*ptr); | 184 | ptr->entry.name = ((char *) ptr) + sizeof(*ptr); |
| 185 | memmove((char *) ptr->entry.name, name, len); | 185 | memmove((char *) ptr->entry.name, name, len); |
| 186 | atomic_set(&ptr->users, 1); | 186 | atomic_set(&ptr->head.users, 1); |
| 187 | tomoyo_fill_path_info(&ptr->entry); | 187 | tomoyo_fill_path_info(&ptr->entry); |
| 188 | list_add_tail(&ptr->list, head); | 188 | list_add_tail(&ptr->head.list, head); |
| 189 | out: | 189 | out: |
| 190 | mutex_unlock(&tomoyo_policy_lock); | 190 | mutex_unlock(&tomoyo_policy_lock); |
| 191 | return ptr ? &ptr->entry : NULL; | 191 | return ptr ? &ptr->entry : NULL; |
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 5cfc72078742..7649dbc6a56b 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c | |||
| @@ -52,16 +52,28 @@ static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) | |||
| 52 | r->param.mount.dir->name, type, flags); | 52 | r->param.mount.dir->name, type, flags); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | /** | ||
| 56 | * tomoyo_check_mount_acl - Check permission for path path path number operation. | ||
| 57 | * | ||
| 58 | * @r: Pointer to "struct tomoyo_request_info". | ||
| 59 | * @ptr: Pointer to "struct tomoyo_acl_info". | ||
| 60 | * | ||
| 61 | * Returns true if granted, false otherwise. | ||
| 62 | */ | ||
| 55 | static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, | 63 | static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, |
| 56 | const struct tomoyo_acl_info *ptr) | 64 | const struct tomoyo_acl_info *ptr) |
| 57 | { | 65 | { |
| 58 | const struct tomoyo_mount_acl *acl = | 66 | const struct tomoyo_mount_acl *acl = |
| 59 | container_of(ptr, typeof(*acl), head); | 67 | container_of(ptr, typeof(*acl), head); |
| 60 | return tomoyo_compare_number_union(r->param.mount.flags, &acl->flags) && | 68 | return tomoyo_compare_number_union(r->param.mount.flags, |
| 61 | tomoyo_compare_name_union(r->param.mount.type, &acl->fs_type) && | 69 | &acl->flags) && |
| 62 | tomoyo_compare_name_union(r->param.mount.dir, &acl->dir_name) && | 70 | tomoyo_compare_name_union(r->param.mount.type, |
| 71 | &acl->fs_type) && | ||
| 72 | tomoyo_compare_name_union(r->param.mount.dir, | ||
| 73 | &acl->dir_name) && | ||
| 63 | (!r->param.mount.need_dev || | 74 | (!r->param.mount.need_dev || |
| 64 | tomoyo_compare_name_union(r->param.mount.dev, &acl->dev_name)); | 75 | tomoyo_compare_name_union(r->param.mount.dev, |
| 76 | &acl->dev_name)); | ||
| 65 | } | 77 | } |
| 66 | 78 | ||
| 67 | /** | 79 | /** |
| @@ -232,13 +244,20 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, | |||
| 232 | return error; | 244 | return error; |
| 233 | } | 245 | } |
| 234 | 246 | ||
| 247 | /** | ||
| 248 | * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry. | ||
| 249 | * | ||
| 250 | * @a: Pointer to "struct tomoyo_acl_info". | ||
| 251 | * @b: Pointer to "struct tomoyo_acl_info". | ||
| 252 | * | ||
| 253 | * Returns true if @a == @b, false otherwise. | ||
| 254 | */ | ||
| 235 | static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, | 255 | static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, |
| 236 | const struct tomoyo_acl_info *b) | 256 | const struct tomoyo_acl_info *b) |
| 237 | { | 257 | { |
| 238 | const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); | 258 | const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); |
| 239 | const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); | 259 | const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); |
| 240 | return tomoyo_same_acl_head(&p1->head, &p2->head) && | 260 | return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && |
| 241 | tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && | ||
| 242 | tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && | 261 | tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && |
| 243 | tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && | 262 | tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && |
| 244 | tomoyo_same_number_union(&p1->flags, &p2->flags); | 263 | tomoyo_same_number_union(&p1->flags, &p2->flags); |
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c index a5bd76d7f6be..6410868c8a3d 100644 --- a/security/tomoyo/securityfs_if.c +++ b/security/tomoyo/securityfs_if.c | |||
| @@ -34,7 +34,7 @@ static int tomoyo_open(struct inode *inode, struct file *file) | |||
| 34 | */ | 34 | */ |
| 35 | static int tomoyo_release(struct inode *inode, struct file *file) | 35 | static int tomoyo_release(struct inode *inode, struct file *file) |
| 36 | { | 36 | { |
| 37 | return tomoyo_close_control(file); | 37 | return tomoyo_close_control(file->private_data); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | /** | 40 | /** |
| @@ -63,7 +63,7 @@ static unsigned int tomoyo_poll(struct file *file, poll_table *wait) | |||
| 63 | static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, | 63 | static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, |
| 64 | loff_t *ppos) | 64 | loff_t *ppos) |
| 65 | { | 65 | { |
| 66 | return tomoyo_read_control(file, buf, count); | 66 | return tomoyo_read_control(file->private_data, buf, count); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | /** | 69 | /** |
| @@ -79,7 +79,7 @@ static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, | |||
| 79 | static ssize_t tomoyo_write(struct file *file, const char __user *buf, | 79 | static ssize_t tomoyo_write(struct file *file, const char __user *buf, |
| 80 | size_t count, loff_t *ppos) | 80 | size_t count, loff_t *ppos) |
| 81 | { | 81 | { |
| 82 | return tomoyo_write_control(file, buf, count); | 82 | return tomoyo_write_control(file->private_data, buf, count); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | /* | 85 | /* |
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 7fb9bbf7021a..abb177c2d7c2 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
| @@ -21,7 +21,7 @@ bool tomoyo_policy_loaded; | |||
| 21 | * @result: Pointer to "unsigned long". | 21 | * @result: Pointer to "unsigned long". |
| 22 | * @str: Pointer to string to parse. | 22 | * @str: Pointer to string to parse. |
| 23 | * | 23 | * |
| 24 | * Returns value type on success, 0 otherwise. | 24 | * Returns one of values in "enum tomoyo_value_type". |
| 25 | * | 25 | * |
| 26 | * The @src is updated to point the first character after the value | 26 | * The @src is updated to point the first character after the value |
| 27 | * on success. | 27 | * on success. |
| @@ -43,7 +43,7 @@ static u8 tomoyo_parse_ulong(unsigned long *result, char **str) | |||
| 43 | } | 43 | } |
| 44 | *result = simple_strtoul(cp, &ep, base); | 44 | *result = simple_strtoul(cp, &ep, base); |
| 45 | if (cp == ep) | 45 | if (cp == ep) |
| 46 | return 0; | 46 | return TOMOYO_VALUE_TYPE_INVALID; |
| 47 | *str = ep; | 47 | *str = ep; |
| 48 | switch (base) { | 48 | switch (base) { |
| 49 | case 16: | 49 | case 16: |
| @@ -93,11 +93,9 @@ bool tomoyo_parse_name_union(const char *filename, | |||
| 93 | return false; | 93 | return false; |
| 94 | if (filename[0] == '@') { | 94 | if (filename[0] == '@') { |
| 95 | ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP); | 95 | ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP); |
| 96 | ptr->is_group = true; | ||
| 97 | return ptr->group != NULL; | 96 | return ptr->group != NULL; |
| 98 | } | 97 | } |
| 99 | ptr->filename = tomoyo_get_name(filename); | 98 | ptr->filename = tomoyo_get_name(filename); |
| 100 | ptr->is_group = false; | ||
| 101 | return ptr->filename != NULL; | 99 | return ptr->filename != NULL; |
| 102 | } | 100 | } |
| 103 | 101 | ||
| @@ -118,17 +116,16 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) | |||
| 118 | if (!tomoyo_correct_word(data)) | 116 | if (!tomoyo_correct_word(data)) |
| 119 | return false; | 117 | return false; |
| 120 | num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP); | 118 | num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP); |
| 121 | num->is_group = true; | ||
| 122 | return num->group != NULL; | 119 | return num->group != NULL; |
| 123 | } | 120 | } |
| 124 | type = tomoyo_parse_ulong(&v, &data); | 121 | type = tomoyo_parse_ulong(&v, &data); |
| 125 | if (!type) | 122 | if (!type) |
| 126 | return false; | 123 | return false; |
| 127 | num->values[0] = v; | 124 | num->values[0] = v; |
| 128 | num->min_type = type; | 125 | num->value_type[0] = type; |
| 129 | if (!*data) { | 126 | if (!*data) { |
| 130 | num->values[1] = v; | 127 | num->values[1] = v; |
| 131 | num->max_type = type; | 128 | num->value_type[1] = type; |
| 132 | return true; | 129 | return true; |
| 133 | } | 130 | } |
| 134 | if (*data++ != '-') | 131 | if (*data++ != '-') |
| @@ -137,7 +134,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) | |||
| 137 | if (!type || *data) | 134 | if (!type || *data) |
| 138 | return false; | 135 | return false; |
| 139 | num->values[1] = v; | 136 | num->values[1] = v; |
| 140 | num->max_type = type; | 137 | num->value_type[1] = type; |
| 141 | return true; | 138 | return true; |
| 142 | } | 139 | } |
| 143 | 140 | ||
| @@ -185,6 +182,30 @@ static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3) | |||
| 185 | } | 182 | } |
| 186 | 183 | ||
| 187 | /** | 184 | /** |
| 185 | * tomoyo_valid - Check whether the character is a valid char. | ||
| 186 | * | ||
| 187 | * @c: The character to check. | ||
| 188 | * | ||
| 189 | * Returns true if @c is a valid character, false otherwise. | ||
| 190 | */ | ||
| 191 | static inline bool tomoyo_valid(const unsigned char c) | ||
| 192 | { | ||
| 193 | return c > ' ' && c < 127; | ||
| 194 | } | ||
| 195 | |||
| 196 | /** | ||
| 197 | * tomoyo_invalid - Check whether the character is an invalid char. | ||
| 198 | * | ||
| 199 | * @c: The character to check. | ||
| 200 | * | ||
| 201 | * Returns true if @c is an invalid character, false otherwise. | ||
| 202 | */ | ||
| 203 | static inline bool tomoyo_invalid(const unsigned char c) | ||
| 204 | { | ||
| 205 | return c && (c <= ' ' || c >= 127); | ||
| 206 | } | ||
| 207 | |||
| 208 | /** | ||
| 188 | * tomoyo_str_starts - Check whether the given string starts with the given keyword. | 209 | * tomoyo_str_starts - Check whether the given string starts with the given keyword. |
| 189 | * | 210 | * |
| 190 | * @src: Pointer to pointer to the string. | 211 | * @src: Pointer to pointer to the string. |
