TOMOYO: Copy directly to userspace buffer.
When userspace program reads policy from /sys/kernel/security/tomoyo/ interface, TOMOYO uses line buffered mode. A line has at least one word. Commit 006dacc "TOMOYO: Support longer pathname." changed a word's max length from 4000 bytes to max kmalloc()able bytes. By that commit, a line's max length changed from 8192 bytes to more than max kmalloc()able bytes. Max number of words in a line remains finite. This patch changes the way of buffering so that all words in a line are firstly directly copied to userspace buffer as much as possible and are secondly queued for next read request. Words queued are guaranteed to be valid until /sys/kernel/security/tomoyo/ interface is close()d. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
5db5a39b64
commit
f23571e866
3 changed files with 510 additions and 470 deletions
File diff suppressed because it is too large
Load diff
|
@ -524,28 +524,11 @@ struct tomoyo_mount_acl {
|
|||
struct tomoyo_number_union flags;
|
||||
};
|
||||
|
||||
#define TOMOYO_MAX_IO_READ_QUEUE 32
|
||||
|
||||
/*
|
||||
* tomoyo_io_buffer is a structure which is used for reading and modifying
|
||||
* configuration via /sys/kernel/security/tomoyo/ interface.
|
||||
* It has many fields. ->read_var1 , ->read_var2 , ->write_var1 are used as
|
||||
* cursors.
|
||||
*
|
||||
* Since the content of /sys/kernel/security/tomoyo/domain_policy is a list of
|
||||
* "struct tomoyo_domain_info" entries and each "struct tomoyo_domain_info"
|
||||
* entry has a list of "struct tomoyo_acl_info", we need two cursors when
|
||||
* reading (one is for traversing tomoyo_domain_list and the other is for
|
||||
* traversing "struct tomoyo_acl_info"->acl_info_list ).
|
||||
*
|
||||
* If a line written to /sys/kernel/security/tomoyo/domain_policy starts with
|
||||
* "select ", TOMOYO seeks the cursor ->read_var1 and ->write_var1 to the
|
||||
* domain with the domainname specified by the rest of that line (NULL is set
|
||||
* if seek failed).
|
||||
* If a line written to /sys/kernel/security/tomoyo/domain_policy starts with
|
||||
* "delete ", TOMOYO deletes an entry or a domain specified by the rest of that
|
||||
* line (->write_var1 is set to NULL if a domain was deleted).
|
||||
* If a line written to /sys/kernel/security/tomoyo/domain_policy starts with
|
||||
* neither "select " nor "delete ", an entry or a domain specified by that line
|
||||
* is appended.
|
||||
* Structure for reading/writing policy via /sys/kernel/security/tomoyo
|
||||
* interfaces.
|
||||
*/
|
||||
struct tomoyo_io_buffer {
|
||||
void (*read) (struct tomoyo_io_buffer *);
|
||||
|
@ -555,26 +538,27 @@ struct tomoyo_io_buffer {
|
|||
struct mutex io_sem;
|
||||
/* Index returned by tomoyo_read_lock(). */
|
||||
int reader_idx;
|
||||
/* The position currently reading from. */
|
||||
struct list_head *read_var1;
|
||||
/* Extra variables for reading. */
|
||||
struct list_head *read_var2;
|
||||
char __user *read_user_buf;
|
||||
int read_user_buf_avail;
|
||||
struct {
|
||||
struct list_head *domain;
|
||||
struct list_head *group;
|
||||
struct list_head *acl;
|
||||
int avail;
|
||||
int step;
|
||||
int query_index;
|
||||
u16 index;
|
||||
u8 bit;
|
||||
u8 w_pos;
|
||||
bool eof;
|
||||
bool print_this_domain_only;
|
||||
bool print_execute_only;
|
||||
const char *w[TOMOYO_MAX_IO_READ_QUEUE];
|
||||
} r;
|
||||
/* The position currently writing to. */
|
||||
struct tomoyo_domain_info *write_var1;
|
||||
/* The step for reading. */
|
||||
int read_step;
|
||||
/* Buffer for reading. */
|
||||
char *read_buf;
|
||||
/* EOF flag for reading. */
|
||||
bool read_eof;
|
||||
/* Read domain ACL of specified PID? */
|
||||
bool read_single_domain;
|
||||
/* Extra variable for reading. */
|
||||
u8 read_bit;
|
||||
/* Read only TOMOYO_TYPE_EXECUTE */
|
||||
bool print_execute_only;
|
||||
/* Bytes available for reading. */
|
||||
int read_avail;
|
||||
/* Size of read buffer. */
|
||||
int readbuf_size;
|
||||
/* Buffer for writing. */
|
||||
|
@ -738,8 +722,7 @@ bool tomoyo_compare_name_union(const struct tomoyo_path_info *name,
|
|||
bool tomoyo_compare_number_union(const unsigned long value,
|
||||
const struct tomoyo_number_union *ptr);
|
||||
int tomoyo_get_mode(const u8 profile, const u8 index);
|
||||
/* Transactional sprintf() for policy dump. */
|
||||
bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
|
||||
void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
/* Check whether the domainname is correct. */
|
||||
bool tomoyo_correct_domain(const unsigned char *domainname);
|
||||
|
@ -761,8 +744,6 @@ bool tomoyo_number_matches_group(const unsigned long min,
|
|||
bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
|
||||
const struct tomoyo_path_info *pattern);
|
||||
|
||||
bool tomoyo_print_number_union(struct tomoyo_io_buffer *head,
|
||||
const struct tomoyo_number_union *ptr);
|
||||
bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num);
|
||||
/* Tokenize a line. */
|
||||
bool tomoyo_tokenize(char *buffer, char *w[], size_t size);
|
||||
|
|
|
@ -234,7 +234,7 @@ unsigned int tomoyo_quota_for_query;
|
|||
*/
|
||||
void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
|
||||
{
|
||||
if (!head->read_eof) {
|
||||
if (!head->r.eof) {
|
||||
const unsigned int policy
|
||||
= atomic_read(&tomoyo_policy_memory_size);
|
||||
const unsigned int query = tomoyo_query_memory_size;
|
||||
|
@ -258,7 +258,7 @@ void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
|
|||
tomoyo_io_printf(head, "Query lists: %10u%s\n", query,
|
||||
buffer);
|
||||
tomoyo_io_printf(head, "Total: %10u\n", policy + query);
|
||||
head->read_eof = true;
|
||||
head->r.eof = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue