binderカーネルバッファ管理

4399 ワード

static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
size_t data_size, size_t offsets_size, int is_async)
{
struct rb_node *n = proc->free_buffers.rb_node;
struct binder_buffer *buffer;
size_t buffer_size;
struct rb_node *best_fit = NULL;
void *has_page_addr;
void *end_page_addr;
size_t size;

if (proc->vma == NULL) {
printk(KERN_ERR "binder: %d: binder_alloc_buf, no vma
",
       proc->pid);
return NULL;
}

size = ALIGN(data_size, sizeof(void *)) +
ALIGN(offsets_size, sizeof(void *));

if (size  binder_user_error("binder: %d: got transaction with invalid "
"size %zd-%zd
", proc->pid, data_size, offsets_size);
return NULL;
}

if (is_async &&
    proc->free_async_space  if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd f"
       "ailed, no async space left
", proc->pid, size);
return NULL;
}

while (n) {
buffer = rb_entry(n, struct binder_buffer, rb_node);
BUG_ON(!buffer->free);
buffer_size = binder_buffer_size(proc, buffer);

if (size  best_fit = n;
n = n->rb_left;
} else if (size > buffer_size)
n = n->rb_right;
else {
best_fit = n;
break;
}
}
if (best_fit == NULL) {
printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd failed, "
       "no address space
", proc->pid, size);
return NULL;
}
if (n == NULL) {
buffer = rb_entry(best_fit, struct binder_buffer, rb_node);
buffer_size = binder_buffer_size(proc, buffer);
}
if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
printk(KERN_INFO "binder: %d: binder_alloc_buf size %zd got buff"
       "er %p size %zd
", proc->pid, size, buffer, buffer_size);

    /*
    #define PAGE_SHIFT   12
    #define PAGE_SIZE   (1UL <     #define PAGE_MASK   (~(PAGE_SIZE-1))
    */
    
has_page_addr =
(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
if (n == NULL) {
if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
buffer_size = size; /* no room for other buffers */
else
buffer_size = size + sizeof(struct binder_buffer);
}
end_page_addr =
(void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
if (end_page_addr > has_page_addr)
end_page_addr = has_page_addr;
if (binder_update_page_range(proc, 1,
    (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL))
return NULL;

rb_erase(best_fit, &proc->free_buffers);
buffer->free = 0;
binder_insert_allocated_buffer(proc, buffer);
if (buffer_size != size) {
struct binder_buffer *new_buffer = (void *)buffer->data + size;
list_add(&new_buffer->entry, &buffer->entry);
new_buffer->free = 1;
binder_insert_free_buffer(proc, new_buffer);
}
if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
printk(KERN_INFO "binder: %d: binder_alloc_buf size %zd got "
       "%p
", proc->pid, size, buffer);
buffer->data_size = data_size;
buffer->offsets_size = offsets_size;
buffer->async_transaction = is_async;
if (is_async) {
proc->free_async_space -= size + sizeof(struct binder_buffer);
if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC_ASYNC)
printk(KERN_INFO "binder: %d: binder_alloc_buf size %zd "
       "async free %zd
", proc->pid, size,
       proc->free_async_space);
}

return buffer;
}

[size=16 px]割り当てカーネルバッファ内で使用し、切り抜き後の新しいカーネルバッファ部分またはすべてが無効な物理メモリに存在する可能性がありますか?トリミング後のbuffer->data+buffer_sizeがページ境界に適切に位置すると、カーネルバッファの終了アドレスもend_に等しいpage_addr、ではbinder_update_page_range(proc, 1, (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr,NULL)が物理メモリを割り当てる場合、切り抜き後の新しいカーネルバッファ構造体には物理メモリが割り当てられていないのではないでしょうか.[/size]