TOMOYO: Return appropriate value to poll().
Tetsuo Handa [Wed, 14 Mar 2012 09:27:49 +0000 (18:27 +0900)]
"struct file_operations"->poll() expects "unsigned int" return value.
All files in /sys/kernel/security/tomoyo/ directory other than
/sys/kernel/security/tomoyo/query and /sys/kernel/security/tomoyo/audit should
return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM rather than -ENOSYS.
Also, /sys/kernel/security/tomoyo/query and /sys/kernel/security/tomoyo/audit
should return POLLOUT | POLLWRNORM rather than 0 when there is no data to read.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <james.l.morris@oracle.com>

security/tomoyo/audit.c
security/tomoyo/common.c
security/tomoyo/common.h
security/tomoyo/securityfs_if.c

index 5ca47ea..7ef9fa3 100644 (file)
@@ -446,11 +446,11 @@ void tomoyo_read_log(struct tomoyo_io_buffer *head)
  * tomoyo_poll_log - Wait for an audit log.
  *
  * @file: Pointer to "struct file".
- * @wait: Pointer to "poll_table".
+ * @wait: Pointer to "poll_table". Maybe NULL.
  *
  * Returns POLLIN | POLLRDNORM when ready to read an audit log.
  */
-int tomoyo_poll_log(struct file *file, poll_table *wait)
+unsigned int tomoyo_poll_log(struct file *file, poll_table *wait)
 {
        if (tomoyo_log_count)
                return POLLIN | POLLRDNORM;
index c47d3ce..d8561c3 100644 (file)
@@ -2111,7 +2111,7 @@ static struct tomoyo_domain_info *tomoyo_find_domain_by_qid
        struct tomoyo_domain_info *domain = NULL;
        spin_lock(&tomoyo_query_list_lock);
        list_for_each_entry(ptr, &tomoyo_query_list, list) {
-               if (ptr->serial != serial || ptr->answer)
+               if (ptr->serial != serial)
                        continue;
                domain = ptr->domain;
                break;
@@ -2130,28 +2130,13 @@ static struct tomoyo_domain_info *tomoyo_find_domain_by_qid
  *
  * Waits for access requests which violated policy in enforcing mode.
  */
-static int tomoyo_poll_query(struct file *file, poll_table *wait)
+static unsigned int tomoyo_poll_query(struct file *file, poll_table *wait)
 {
-       struct list_head *tmp;
-       bool found = false;
-       u8 i;
-       for (i = 0; i < 2; i++) {
-               spin_lock(&tomoyo_query_list_lock);
-               list_for_each(tmp, &tomoyo_query_list) {
-                       struct tomoyo_query *ptr =
-                               list_entry(tmp, typeof(*ptr), list);
-                       if (ptr->answer)
-                               continue;
-                       found = true;
-                       break;
-               }
-               spin_unlock(&tomoyo_query_list_lock);
-               if (found)
-                       return POLLIN | POLLRDNORM;
-               if (i)
-                       break;
-               poll_wait(file, &tomoyo_query_wait, wait);
-       }
+       if (!list_empty(&tomoyo_query_list))
+               return POLLIN | POLLRDNORM;
+       poll_wait(file, &tomoyo_query_wait, wait);
+       if (!list_empty(&tomoyo_query_list))
+               return POLLIN | POLLRDNORM;
        return 0;
 }
 
@@ -2175,8 +2160,6 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head)
        spin_lock(&tomoyo_query_list_lock);
        list_for_each(tmp, &tomoyo_query_list) {
                struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
-               if (ptr->answer)
-                       continue;
                if (pos++ != head->r.query_index)
                        continue;
                len = ptr->query_len;
@@ -2194,8 +2177,6 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head)
        spin_lock(&tomoyo_query_list_lock);
        list_for_each(tmp, &tomoyo_query_list) {
                struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
-               if (ptr->answer)
-                       continue;
                if (pos++ != head->r.query_index)
                        continue;
                /*
@@ -2243,8 +2224,10 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
                struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
                if (ptr->serial != serial)
                        continue;
-               if (!ptr->answer)
-                       ptr->answer = answer;
+               ptr->answer = answer;
+               /* Remove from tomoyo_query_list. */
+               if (ptr->answer)
+                       list_del_init(&ptr->list);
                break;
        }
        spin_unlock(&tomoyo_query_list_lock);
@@ -2477,18 +2460,17 @@ int tomoyo_open_control(const u8 type, struct file *file)
  * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface.
  *
  * @file: Pointer to "struct file".
- * @wait: Pointer to "poll_table".
+ * @wait: Pointer to "poll_table". Maybe NULL.
  *
- * Waits for read readiness.
- * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd and
- * /sys/kernel/security/tomoyo/audit is handled by /usr/sbin/tomoyo-auditd.
+ * Returns POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM if ready to read/write,
+ * POLLOUT | POLLWRNORM otherwise.
  */
-int tomoyo_poll_control(struct file *file, poll_table *wait)
+unsigned int tomoyo_poll_control(struct file *file, poll_table *wait)
 {
        struct tomoyo_io_buffer *head = file->private_data;
-       if (!head->poll)
-               return -ENOSYS;
-       return head->poll(file, wait);
+       if (head->poll)
+               return head->poll(file, wait) | POLLOUT | POLLWRNORM;
+       return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
 }
 
 /**
index 9512222..30fd983 100644 (file)
@@ -788,7 +788,7 @@ struct tomoyo_acl_param {
 struct tomoyo_io_buffer {
        void (*read) (struct tomoyo_io_buffer *);
        int (*write) (struct tomoyo_io_buffer *);
-       int (*poll) (struct file *file, poll_table *wait);
+       unsigned int (*poll) (struct file *file, poll_table *wait);
        /* Exclusive lock for this structure.   */
        struct mutex io_sem;
        char __user *read_user_buf;
@@ -981,8 +981,8 @@ int tomoyo_path_number_perm(const u8 operation, struct path *path,
                            unsigned long number);
 int tomoyo_path_perm(const u8 operation, struct path *path,
                     const char *target);
-int tomoyo_poll_control(struct file *file, poll_table *wait);
-int tomoyo_poll_log(struct file *file, poll_table *wait);
+unsigned int tomoyo_poll_control(struct file *file, poll_table *wait);
+unsigned int tomoyo_poll_log(struct file *file, poll_table *wait);
 int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
                                  int addr_len);
 int tomoyo_socket_connect_permission(struct socket *sock,
index 482b2a5..8592f2f 100644 (file)
@@ -157,9 +157,10 @@ static int tomoyo_release(struct inode *inode, struct file *file)
  * tomoyo_poll - poll() for /sys/kernel/security/tomoyo/ interface.
  *
  * @file: Pointer to "struct file".
- * @wait: Pointer to "poll_table".
+ * @wait: Pointer to "poll_table". Maybe NULL.
  *
- * Returns 0 on success, negative value otherwise.
+ * Returns POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM if ready to read/write,
+ * POLLOUT | POLLWRNORM otherwise.
  */
 static unsigned int tomoyo_poll(struct file *file, poll_table *wait)
 {