Sfoglia il codice sorgente

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>
Tetsuo Handa 15 anni fa
parent
commit
f23571e866
3 ha cambiato i file con 466 aggiunte e 408 eliminazioni
  1. 442 365
      security/tomoyo/common.c
  2. 22 41
      security/tomoyo/common.h
  3. 2 2
      security/tomoyo/memory.c

File diff suppressed because it is too large
+ 442 - 365
security/tomoyo/common.c


+ 22 - 41
security/tomoyo/common.h

@@ -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);

+ 2 - 2
security/tomoyo/memory.c

@@ -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;
 	}
 }
 

Some files were not shown because too many files changed in this diff