Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

binder: Add support for file-descriptor arrays

This patch introduces a new binder_fd_array object,
that allows us to support one or more file descriptors
embedded in a buffer that is scatter-gathered.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Martijn Coenen <maco@google.com>
Cc: Arve Hjønnevåg <arve@android.com>
Cc: Amit Pundir <amit.pundir@linaro.org>
Cc: Serban Constantinescu <serban.constantinescu@arm.com>
Cc: Dmitry Shmidt <dimitrysh@google.com>
Cc: Rom Lemarchand <romlem@google.com>
Cc: Android Kernel Team <kernel-team@android.com>
Signed-off-by: Martijn Coenen <maco@google.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Martijn Coenen and committed by
Greg Kroah-Hartman
def95c73 7980240b

+165
+137
drivers/android/binder.c
··· 155 155 #define to_binder_buffer_object(hdr) \ 156 156 container_of(hdr, struct binder_buffer_object, hdr) 157 157 158 + #define to_binder_fd_array_object(hdr) \ 159 + container_of(hdr, struct binder_fd_array_object, hdr) 160 + 158 161 enum binder_stat_types { 159 162 BINDER_STAT_PROC, 160 163 BINDER_STAT_THREAD, ··· 1313 1310 case BINDER_TYPE_PTR: 1314 1311 object_size = sizeof(struct binder_buffer_object); 1315 1312 break; 1313 + case BINDER_TYPE_FDA: 1314 + object_size = sizeof(struct binder_fd_array_object); 1315 + break; 1316 1316 default: 1317 1317 return 0; 1318 1318 } ··· 1509 1503 * transaction buffer gets freed 1510 1504 */ 1511 1505 break; 1506 + case BINDER_TYPE_FDA: { 1507 + struct binder_fd_array_object *fda; 1508 + struct binder_buffer_object *parent; 1509 + uintptr_t parent_buffer; 1510 + u32 *fd_array; 1511 + size_t fd_index; 1512 + binder_size_t fd_buf_size; 1513 + 1514 + fda = to_binder_fd_array_object(hdr); 1515 + parent = binder_validate_ptr(buffer, fda->parent, 1516 + off_start, 1517 + offp - off_start); 1518 + if (!parent) { 1519 + pr_err("transaction release %d bad parent offset", 1520 + debug_id); 1521 + continue; 1522 + } 1523 + /* 1524 + * Since the parent was already fixed up, convert it 1525 + * back to kernel address space to access it 1526 + */ 1527 + parent_buffer = parent->buffer - 1528 + proc->user_buffer_offset; 1529 + 1530 + fd_buf_size = sizeof(u32) * fda->num_fds; 1531 + if (fda->num_fds >= SIZE_MAX / sizeof(u32)) { 1532 + pr_err("transaction release %d invalid number of fds (%lld)\n", 1533 + debug_id, (u64)fda->num_fds); 1534 + continue; 1535 + } 1536 + if (fd_buf_size > parent->length || 1537 + fda->parent_offset > parent->length - fd_buf_size) { 1538 + /* No space for all file descriptors here. */ 1539 + pr_err("transaction release %d not enough space for %lld fds in buffer\n", 1540 + debug_id, (u64)fda->num_fds); 1541 + continue; 1542 + } 1543 + fd_array = (u32 *)(parent_buffer + fda->parent_offset); 1544 + for (fd_index = 0; fd_index < fda->num_fds; fd_index++) 1545 + task_close_fd(proc, fd_array[fd_index]); 1546 + } break; 1512 1547 default: 1513 1548 pr_err("transaction release %d bad object type %x\n", 1514 1549 debug_id, hdr->type); ··· 1717 1670 err_fget: 1718 1671 err_fd_not_accepted: 1719 1672 return ret; 1673 + } 1674 + 1675 + static int binder_translate_fd_array(struct binder_fd_array_object *fda, 1676 + struct binder_buffer_object *parent, 1677 + struct binder_transaction *t, 1678 + struct binder_thread *thread, 1679 + struct binder_transaction *in_reply_to) 1680 + { 1681 + binder_size_t fdi, fd_buf_size, num_installed_fds; 1682 + int target_fd; 1683 + uintptr_t parent_buffer; 1684 + u32 *fd_array; 1685 + struct binder_proc *proc = thread->proc; 1686 + struct binder_proc *target_proc = t->to_proc; 1687 + 1688 + fd_buf_size = sizeof(u32) * fda->num_fds; 1689 + if (fda->num_fds >= SIZE_MAX / sizeof(u32)) { 1690 + binder_user_error("%d:%d got transaction with invalid number of fds (%lld)\n", 1691 + proc->pid, thread->pid, (u64)fda->num_fds); 1692 + return -EINVAL; 1693 + } 1694 + if (fd_buf_size > parent->length || 1695 + fda->parent_offset > parent->length - fd_buf_size) { 1696 + /* No space for all file descriptors here. */ 1697 + binder_user_error("%d:%d not enough space to store %lld fds in buffer\n", 1698 + proc->pid, thread->pid, (u64)fda->num_fds); 1699 + return -EINVAL; 1700 + } 1701 + /* 1702 + * Since the parent was already fixed up, convert it 1703 + * back to the kernel address space to access it 1704 + */ 1705 + parent_buffer = parent->buffer - target_proc->user_buffer_offset; 1706 + fd_array = (u32 *)(parent_buffer + fda->parent_offset); 1707 + if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) { 1708 + binder_user_error("%d:%d parent offset not aligned correctly.\n", 1709 + proc->pid, thread->pid); 1710 + return -EINVAL; 1711 + } 1712 + for (fdi = 0; fdi < fda->num_fds; fdi++) { 1713 + target_fd = binder_translate_fd(fd_array[fdi], t, thread, 1714 + in_reply_to); 1715 + if (target_fd < 0) 1716 + goto err_translate_fd_failed; 1717 + fd_array[fdi] = target_fd; 1718 + } 1719 + return 0; 1720 + 1721 + err_translate_fd_failed: 1722 + /* 1723 + * Failed to allocate fd or security error, free fds 1724 + * installed so far. 1725 + */ 1726 + num_installed_fds = fdi; 1727 + for (fdi = 0; fdi < num_installed_fds; fdi++) 1728 + task_close_fd(target_proc, fd_array[fdi]); 1729 + return target_fd; 1720 1730 } 1721 1731 1722 1732 static int binder_fixup_parent(struct binder_transaction *t, ··· 2104 2000 fp->pad_binder = 0; 2105 2001 fp->fd = target_fd; 2106 2002 } break; 2003 + case BINDER_TYPE_FDA: { 2004 + struct binder_fd_array_object *fda = 2005 + to_binder_fd_array_object(hdr); 2006 + struct binder_buffer_object *parent = 2007 + binder_validate_ptr(t->buffer, fda->parent, 2008 + off_start, 2009 + offp - off_start); 2010 + if (!parent) { 2011 + binder_user_error("%d:%d got transaction with invalid parent offset or type\n", 2012 + proc->pid, thread->pid); 2013 + return_error = BR_FAILED_REPLY; 2014 + goto err_bad_parent; 2015 + } 2016 + if (!binder_validate_fixup(t->buffer, off_start, 2017 + parent, fda->parent_offset, 2018 + last_fixup_obj, 2019 + last_fixup_min_off)) { 2020 + binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n", 2021 + proc->pid, thread->pid); 2022 + return_error = BR_FAILED_REPLY; 2023 + goto err_bad_parent; 2024 + } 2025 + ret = binder_translate_fd_array(fda, parent, t, thread, 2026 + in_reply_to); 2027 + if (ret < 0) { 2028 + return_error = BR_FAILED_REPLY; 2029 + goto err_translate_failed; 2030 + } 2031 + last_fixup_obj = parent; 2032 + last_fixup_min_off = 2033 + fda->parent_offset + sizeof(u32) * fda->num_fds; 2034 + } break; 2107 2035 case BINDER_TYPE_PTR: { 2108 2036 struct binder_buffer_object *bp = 2109 2037 to_binder_buffer_object(hdr); ··· 2206 2070 err_translate_failed: 2207 2071 err_bad_object_type: 2208 2072 err_bad_offset: 2073 + err_bad_parent: 2209 2074 err_copy_data_failed: 2210 2075 trace_binder_transaction_failed_buffer_release(t->buffer); 2211 2076 binder_transaction_buffer_release(target_proc, t->buffer, offp);
+28
include/uapi/linux/android/binder.h
··· 33 33 BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), 34 34 BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), 35 35 BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), 36 + BINDER_TYPE_FDA = B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE), 36 37 BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE), 37 38 }; 38 39 ··· 128 127 129 128 enum { 130 129 BINDER_BUFFER_FLAG_HAS_PARENT = 0x01, 130 + }; 131 + 132 + /* struct binder_fd_array_object - object describing an array of fds in a buffer 133 + * @hdr: common header structure 134 + * @num_fds: number of file descriptors in the buffer 135 + * @parent: index in offset array to buffer holding the fd array 136 + * @parent_offset: start offset of fd array in the buffer 137 + * 138 + * A binder_fd_array object represents an array of file 139 + * descriptors embedded in a binder_buffer_object. It is 140 + * different from a regular binder_buffer_object because it 141 + * describes a list of file descriptors to fix up, not an opaque 142 + * blob of memory, and hence the kernel needs to treat it differently. 143 + * 144 + * An example of how this would be used is with Android's 145 + * native_handle_t object, which is a struct with a list of integers 146 + * and a list of file descriptors. The native_handle_t struct itself 147 + * will be represented by a struct binder_buffer_objct, whereas the 148 + * embedded list of file descriptors is represented by a 149 + * struct binder_fd_array_object with that binder_buffer_object as 150 + * a parent. 151 + */ 152 + struct binder_fd_array_object { 153 + struct binder_object_header hdr; 154 + binder_size_t num_fds; 155 + binder_size_t parent; 156 + binder_size_t parent_offset; 131 157 }; 132 158 133 159 /*