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;
|
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
|
* Structure for reading/writing policy via /sys/kernel/security/tomoyo
|
||||||
* configuration via /sys/kernel/security/tomoyo/ interface.
|
* interfaces.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
struct tomoyo_io_buffer {
|
struct tomoyo_io_buffer {
|
||||||
void (*read) (struct tomoyo_io_buffer *);
|
void (*read) (struct tomoyo_io_buffer *);
|
||||||
|
@ -555,26 +538,27 @@ struct tomoyo_io_buffer {
|
||||||
struct mutex io_sem;
|
struct mutex io_sem;
|
||||||
/* Index returned by tomoyo_read_lock(). */
|
/* Index returned by tomoyo_read_lock(). */
|
||||||
int reader_idx;
|
int reader_idx;
|
||||||
/* The position currently reading from. */
|
char __user *read_user_buf;
|
||||||
struct list_head *read_var1;
|
int read_user_buf_avail;
|
||||||
/* Extra variables for reading. */
|
struct {
|
||||||
struct list_head *read_var2;
|
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. */
|
/* The position currently writing to. */
|
||||||
struct tomoyo_domain_info *write_var1;
|
struct tomoyo_domain_info *write_var1;
|
||||||
/* The step for reading. */
|
|
||||||
int read_step;
|
|
||||||
/* Buffer for reading. */
|
/* Buffer for reading. */
|
||||||
char *read_buf;
|
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. */
|
/* Size of read buffer. */
|
||||||
int readbuf_size;
|
int readbuf_size;
|
||||||
/* Buffer for writing. */
|
/* 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,
|
bool tomoyo_compare_number_union(const unsigned long value,
|
||||||
const struct tomoyo_number_union *ptr);
|
const struct tomoyo_number_union *ptr);
|
||||||
int tomoyo_get_mode(const u8 profile, const u8 index);
|
int tomoyo_get_mode(const u8 profile, const u8 index);
|
||||||
/* Transactional sprintf() for policy dump. */
|
void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
|
||||||
bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
|
|
||||||
__attribute__ ((format(printf, 2, 3)));
|
__attribute__ ((format(printf, 2, 3)));
|
||||||
/* Check whether the domainname is correct. */
|
/* Check whether the domainname is correct. */
|
||||||
bool tomoyo_correct_domain(const unsigned char *domainname);
|
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,
|
bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
|
||||||
const struct tomoyo_path_info *pattern);
|
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);
|
bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num);
|
||||||
/* Tokenize a line. */
|
/* Tokenize a line. */
|
||||||
bool tomoyo_tokenize(char *buffer, char *w[], size_t size);
|
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)
|
void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
|
||||||
{
|
{
|
||||||
if (!head->read_eof) {
|
if (!head->r.eof) {
|
||||||
const unsigned int policy
|
const unsigned int policy
|
||||||
= atomic_read(&tomoyo_policy_memory_size);
|
= atomic_read(&tomoyo_policy_memory_size);
|
||||||
const unsigned int query = tomoyo_query_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,
|
tomoyo_io_printf(head, "Query lists: %10u%s\n", query,
|
||||||
buffer);
|
buffer);
|
||||||
tomoyo_io_printf(head, "Total: %10u\n", policy + query);
|
tomoyo_io_printf(head, "Total: %10u\n", policy + query);
|
||||||
head->read_eof = true;
|
head->r.eof = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue