Skip to content

Commit 8ced0c6

Browse files
Todd Kjosgregkh
authored andcommitted
binder: add functions to copy to/from binder buffers
Avoid vm_area when copying to or from binder buffers. Instead, new copy functions are added that copy from kernel space to binder buffer space. These use kmap_atomic() and kunmap_atomic() to create temporary mappings and then memcpy() is used to copy within that page. Also, kmap_atomic() / kunmap_atomic() use the appropriate cache flushing to support VIVT cache architectures. Allow binder to build if CPU_CACHE_VIVT is defined. Several uses of the new functions are added here. More to follow in subsequent patches. Signed-off-by: Todd Kjos <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1a7c3d9 commit 8ced0c6

File tree

4 files changed

+147
-45
lines changed

4 files changed

+147
-45
lines changed

drivers/android/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ if ANDROID
1010

1111
config ANDROID_BINDER_IPC
1212
bool "Android Binder IPC Driver"
13-
depends on MMU && !CPU_CACHE_VIVT
13+
depends on MMU
1414
default n
1515
---help---
1616
Binder is used in Android for both communication between processes,

drivers/android/binder.c

Lines changed: 75 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,14 +2244,22 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
22442244
off_end = (void *)off_start + buffer->offsets_size;
22452245
for (offp = off_start; offp < off_end; offp++) {
22462246
struct binder_object_header *hdr;
2247-
size_t object_size = binder_validate_object(buffer, *offp);
2248-
2247+
size_t object_size;
2248+
binder_size_t object_offset;
2249+
binder_size_t buffer_offset = (uintptr_t)offp -
2250+
(uintptr_t)buffer->data;
2251+
2252+
binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
2253+
buffer, buffer_offset,
2254+
sizeof(object_offset));
2255+
object_size = binder_validate_object(buffer, object_offset);
22492256
if (object_size == 0) {
22502257
pr_err("transaction release %d bad object at offset %lld, size %zd\n",
2251-
debug_id, (u64)*offp, buffer->data_size);
2258+
debug_id, (u64)object_offset, buffer->data_size);
22522259
continue;
22532260
}
2254-
hdr = (struct binder_object_header *)(buffer->data + *offp);
2261+
hdr = (struct binder_object_header *)
2262+
(buffer->data + object_offset);
22552263
switch (hdr->type) {
22562264
case BINDER_TYPE_BINDER:
22572265
case BINDER_TYPE_WEAK_BINDER: {
@@ -2359,8 +2367,20 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
23592367
continue;
23602368
}
23612369
fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset);
2362-
for (fd_index = 0; fd_index < fda->num_fds; fd_index++)
2363-
binder_deferred_fd_close(fd_array[fd_index]);
2370+
for (fd_index = 0; fd_index < fda->num_fds;
2371+
fd_index++) {
2372+
u32 fd;
2373+
binder_size_t offset =
2374+
(uintptr_t)&fd_array[fd_index] -
2375+
(uintptr_t)buffer->data;
2376+
2377+
binder_alloc_copy_from_buffer(&proc->alloc,
2378+
&fd,
2379+
buffer,
2380+
offset,
2381+
sizeof(fd));
2382+
binder_deferred_fd_close(fd);
2383+
}
23642384
} break;
23652385
default:
23662386
pr_err("transaction release %d bad object type %x\n",
@@ -2496,7 +2516,7 @@ static int binder_translate_handle(struct flat_binder_object *fp,
24962516
return ret;
24972517
}
24982518

2499-
static int binder_translate_fd(u32 *fdp,
2519+
static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
25002520
struct binder_transaction *t,
25012521
struct binder_thread *thread,
25022522
struct binder_transaction *in_reply_to)
@@ -2507,7 +2527,6 @@ static int binder_translate_fd(u32 *fdp,
25072527
struct file *file;
25082528
int ret = 0;
25092529
bool target_allows_fd;
2510-
int fd = *fdp;
25112530

25122531
if (in_reply_to)
25132532
target_allows_fd = !!(in_reply_to->flags & TF_ACCEPT_FDS);
@@ -2546,7 +2565,7 @@ static int binder_translate_fd(u32 *fdp,
25462565
goto err_alloc;
25472566
}
25482567
fixup->file = file;
2549-
fixup->offset = (uintptr_t)fdp - (uintptr_t)t->buffer->data;
2568+
fixup->offset = fd_offset;
25502569
trace_binder_transaction_fd_send(t, fd, fixup->offset);
25512570
list_add_tail(&fixup->fixup_entry, &t->fd_fixups);
25522571

@@ -2598,8 +2617,17 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
25982617
return -EINVAL;
25992618
}
26002619
for (fdi = 0; fdi < fda->num_fds; fdi++) {
2601-
int ret = binder_translate_fd(&fd_array[fdi], t, thread,
2602-
in_reply_to);
2620+
u32 fd;
2621+
int ret;
2622+
binder_size_t offset =
2623+
(uintptr_t)&fd_array[fdi] -
2624+
(uintptr_t)t->buffer->data;
2625+
2626+
binder_alloc_copy_from_buffer(&target_proc->alloc,
2627+
&fd, t->buffer,
2628+
offset, sizeof(fd));
2629+
ret = binder_translate_fd(fd, offset, t, thread,
2630+
in_reply_to);
26032631
if (ret < 0)
26042632
return ret;
26052633
}
@@ -3066,7 +3094,9 @@ static void binder_transaction(struct binder_proc *proc,
30663094

30673095
t->security_ctx = (uintptr_t)kptr +
30683096
binder_alloc_get_user_buffer_offset(&target_proc->alloc);
3069-
memcpy(kptr, secctx, secctx_sz);
3097+
binder_alloc_copy_to_buffer(&target_proc->alloc,
3098+
t->buffer, buf_offset,
3099+
secctx, secctx_sz);
30703100
security_release_secctx(secctx, secctx_sz);
30713101
secctx = NULL;
30723102
}
@@ -3128,11 +3158,21 @@ static void binder_transaction(struct binder_proc *proc,
31283158
off_min = 0;
31293159
for (; offp < off_end; offp++) {
31303160
struct binder_object_header *hdr;
3131-
size_t object_size = binder_validate_object(t->buffer, *offp);
3132-
3133-
if (object_size == 0 || *offp < off_min) {
3161+
size_t object_size;
3162+
binder_size_t object_offset;
3163+
binder_size_t buffer_offset =
3164+
(uintptr_t)offp - (uintptr_t)t->buffer->data;
3165+
3166+
binder_alloc_copy_from_buffer(&target_proc->alloc,
3167+
&object_offset,
3168+
t->buffer,
3169+
buffer_offset,
3170+
sizeof(object_offset));
3171+
object_size = binder_validate_object(t->buffer, object_offset);
3172+
if (object_size == 0 || object_offset < off_min) {
31343173
binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
3135-
proc->pid, thread->pid, (u64)*offp,
3174+
proc->pid, thread->pid,
3175+
(u64)object_offset,
31363176
(u64)off_min,
31373177
(u64)t->buffer->data_size);
31383178
return_error = BR_FAILED_REPLY;
@@ -3141,8 +3181,9 @@ static void binder_transaction(struct binder_proc *proc,
31413181
goto err_bad_offset;
31423182
}
31433183

3144-
hdr = (struct binder_object_header *)(t->buffer->data + *offp);
3145-
off_min = *offp + object_size;
3184+
hdr = (struct binder_object_header *)
3185+
(t->buffer->data + object_offset);
3186+
off_min = object_offset + object_size;
31463187
switch (hdr->type) {
31473188
case BINDER_TYPE_BINDER:
31483189
case BINDER_TYPE_WEAK_BINDER: {
@@ -3173,8 +3214,10 @@ static void binder_transaction(struct binder_proc *proc,
31733214

31743215
case BINDER_TYPE_FD: {
31753216
struct binder_fd_object *fp = to_binder_fd_object(hdr);
3176-
int ret = binder_translate_fd(&fp->fd, t, thread,
3177-
in_reply_to);
3217+
binder_size_t fd_offset = object_offset +
3218+
(uintptr_t)&fp->fd - (uintptr_t)fp;
3219+
int ret = binder_translate_fd(fp->fd, fd_offset, t,
3220+
thread, in_reply_to);
31783221

31793222
if (ret < 0) {
31803223
return_error = BR_FAILED_REPLY;
@@ -3967,6 +4010,7 @@ static int binder_wait_for_work(struct binder_thread *thread,
39674010

39684011
/**
39694012
* binder_apply_fd_fixups() - finish fd translation
4013+
* @proc: binder_proc associated @t->buffer
39704014
* @t: binder transaction with list of fd fixups
39714015
*
39724016
* Now that we are in the context of the transaction target
@@ -3978,14 +4022,14 @@ static int binder_wait_for_work(struct binder_thread *thread,
39784022
* fput'ing files that have not been processed and ksys_close'ing
39794023
* any fds that have already been allocated.
39804024
*/
3981-
static int binder_apply_fd_fixups(struct binder_transaction *t)
4025+
static int binder_apply_fd_fixups(struct binder_proc *proc,
4026+
struct binder_transaction *t)
39824027
{
39834028
struct binder_txn_fd_fixup *fixup, *tmp;
39844029
int ret = 0;
39854030

39864031
list_for_each_entry(fixup, &t->fd_fixups, fixup_entry) {
39874032
int fd = get_unused_fd_flags(O_CLOEXEC);
3988-
u32 *fdp;
39894033

39904034
if (fd < 0) {
39914035
binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -4000,33 +4044,20 @@ static int binder_apply_fd_fixups(struct binder_transaction *t)
40004044
trace_binder_transaction_fd_recv(t, fd, fixup->offset);
40014045
fd_install(fd, fixup->file);
40024046
fixup->file = NULL;
4003-
fdp = (u32 *)(t->buffer->data + fixup->offset);
4004-
/*
4005-
* This store can cause problems for CPUs with a
4006-
* VIVT cache (eg ARMv5) since the cache cannot
4007-
* detect virtual aliases to the same physical cacheline.
4008-
* To support VIVT, this address and the user-space VA
4009-
* would both need to be flushed. Since this kernel
4010-
* VA is not constructed via page_to_virt(), we can't
4011-
* use flush_dcache_page() on it, so we'd have to use
4012-
* an internal function. If devices with VIVT ever
4013-
* need to run Android, we'll either need to go back
4014-
* to patching the translated fd from the sender side
4015-
* (using the non-standard kernel functions), or rework
4016-
* how the kernel uses the buffer to use page_to_virt()
4017-
* addresses instead of allocating in our own vm area.
4018-
*
4019-
* For now, we disable compilation if CONFIG_CPU_CACHE_VIVT.
4020-
*/
4021-
*fdp = fd;
4047+
binder_alloc_copy_to_buffer(&proc->alloc, t->buffer,
4048+
fixup->offset, &fd,
4049+
sizeof(u32));
40224050
}
40234051
list_for_each_entry_safe(fixup, tmp, &t->fd_fixups, fixup_entry) {
40244052
if (fixup->file) {
40254053
fput(fixup->file);
40264054
} else if (ret) {
4027-
u32 *fdp = (u32 *)(t->buffer->data + fixup->offset);
4055+
u32 fd;
40284056

4029-
binder_deferred_fd_close(*fdp);
4057+
binder_alloc_copy_from_buffer(&proc->alloc, &fd,
4058+
t->buffer, fixup->offset,
4059+
sizeof(fd));
4060+
binder_deferred_fd_close(fd);
40304061
}
40314062
list_del(&fixup->fixup_entry);
40324063
kfree(fixup);
@@ -4324,7 +4355,7 @@ static int binder_thread_read(struct binder_proc *proc,
43244355
trd->sender_pid = 0;
43254356
}
43264357

4327-
ret = binder_apply_fd_fixups(t);
4358+
ret = binder_apply_fd_fixups(proc, t);
43284359
if (ret) {
43294360
struct binder_buffer *buffer = t->buffer;
43304361
bool oneway = !!(t->flags & TF_ONE_WAY);

drivers/android/binder_alloc.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,3 +1166,62 @@ binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc,
11661166
}
11671167
return 0;
11681168
}
1169+
1170+
static void binder_alloc_do_buffer_copy(struct binder_alloc *alloc,
1171+
bool to_buffer,
1172+
struct binder_buffer *buffer,
1173+
binder_size_t buffer_offset,
1174+
void *ptr,
1175+
size_t bytes)
1176+
{
1177+
/* All copies must be 32-bit aligned and 32-bit size */
1178+
BUG_ON(!check_buffer(alloc, buffer, buffer_offset, bytes));
1179+
1180+
while (bytes) {
1181+
unsigned long size;
1182+
struct page *page;
1183+
pgoff_t pgoff;
1184+
void *tmpptr;
1185+
void *base_ptr;
1186+
1187+
page = binder_alloc_get_page(alloc, buffer,
1188+
buffer_offset, &pgoff);
1189+
size = min_t(size_t, bytes, PAGE_SIZE - pgoff);
1190+
base_ptr = kmap_atomic(page);
1191+
tmpptr = base_ptr + pgoff;
1192+
if (to_buffer)
1193+
memcpy(tmpptr, ptr, size);
1194+
else
1195+
memcpy(ptr, tmpptr, size);
1196+
/*
1197+
* kunmap_atomic() takes care of flushing the cache
1198+
* if this device has VIVT cache arch
1199+
*/
1200+
kunmap_atomic(base_ptr);
1201+
bytes -= size;
1202+
pgoff = 0;
1203+
ptr = ptr + size;
1204+
buffer_offset += size;
1205+
}
1206+
}
1207+
1208+
void binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
1209+
struct binder_buffer *buffer,
1210+
binder_size_t buffer_offset,
1211+
void *src,
1212+
size_t bytes)
1213+
{
1214+
binder_alloc_do_buffer_copy(alloc, true, buffer, buffer_offset,
1215+
src, bytes);
1216+
}
1217+
1218+
void binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
1219+
void *dest,
1220+
struct binder_buffer *buffer,
1221+
binder_size_t buffer_offset,
1222+
size_t bytes)
1223+
{
1224+
binder_alloc_do_buffer_copy(alloc, false, buffer, buffer_offset,
1225+
dest, bytes);
1226+
}
1227+

drivers/android/binder_alloc.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,5 +191,17 @@ binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc,
191191
const void __user *from,
192192
size_t bytes);
193193

194+
void binder_alloc_copy_to_buffer(struct binder_alloc *alloc,
195+
struct binder_buffer *buffer,
196+
binder_size_t buffer_offset,
197+
void *src,
198+
size_t bytes);
199+
200+
void binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
201+
void *dest,
202+
struct binder_buffer *buffer,
203+
binder_size_t buffer_offset,
204+
size_t bytes);
205+
194206
#endif /* _LINUX_BINDER_ALLOC_H */
195207

0 commit comments

Comments
 (0)