History

binder: create node flag to request sender's security context

To allow servers to verify client identity, allow a node flag to be set that causes the sender's security context to be delivered with the transaction. The BR_TRANSACTION command is extended in BR_TRANSACTION_SEC_CTX to contain a pointer to the security context string.

Todd Kjos committed 7 years ago

Commit ec741361 parent 8fdf9062 files · +102 −23Browse files

Unified · Split

2 files
  1. drivers/android/binder.c +83 −23
  2. include/uapi/linux/android/binder.h +19 −0
drivers/android/binder.c+83−23
@@ -329,6 +329,8 @@ struct binder_error { · 328 unmodified lines
329 * (invariant after initialized)329 * (invariant after initialized)
330 * @min_priority: minimum scheduling priority330 * @min_priority: minimum scheduling priority
331 * (invariant after initialized)331 * (invariant after initialized)
332 * @txn_security_ctx: require sender's security context
333 * (invariant after initialized)
332 * @async_todo: list of async work items334 * @async_todo: list of async work items
333 * (protected by @proc->inner_lock)335 * (protected by @proc->inner_lock)
334 *336 *
@@ -365,6 +367,7 @@ struct binder_node { · 30 unmodified lines
365 * invariant after initialization367 * invariant after initialization
366 */368 */
367 u8 accept_fds:1;369 u8 accept_fds:1;
370 u8 txn_security_ctx:1;
368 u8 min_priority;371 u8 min_priority;
369 };372 };
370 bool has_async_transaction;373 bool has_async_transaction;
@@ -615,6 +618,7 @@ struct binder_transaction { · 244 unmodified lines
615 long saved_priority;618 long saved_priority;
616 kuid_t sender_euid;619 kuid_t sender_euid;
617 struct list_head fd_fixups;620 struct list_head fd_fixups;
621 binder_uintptr_t security_ctx;
618 /**622 /**
619 * @lock: protects @from, @to_proc, and @to_thread623 * @lock: protects @from, @to_proc, and @to_thread
620 *624 *
@@ -1152,6 +1156,7 @@ static struct binder_node *binder_init_node_ilocked( · 531 unmodified lines
1152 node->work.type = BINDER_WORK_NODE;1156 node->work.type = BINDER_WORK_NODE;
1153 node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;1157 node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
1154 node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);1158 node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
1159 node->txn_security_ctx = !!(flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX);
1155 spin_lock_init(&node->lock);1160 spin_lock_init(&node->lock);
1156 INIT_LIST_HEAD(&node->work.entry);1161 INIT_LIST_HEAD(&node->work.entry);
1157 INIT_LIST_HEAD(&node->async_todo);1162 INIT_LIST_HEAD(&node->async_todo);
@@ -2778,6 +2783,8 @@ static void binder_transaction(struct binder_proc *proc, · 1620 unmodified lines
2778 binder_size_t last_fixup_min_off = 0;2783 binder_size_t last_fixup_min_off = 0;
2779 struct binder_context *context = proc->context;2784 struct binder_context *context = proc->context;
2780 int t_debug_id = atomic_inc_return(&binder_last_id);2785 int t_debug_id = atomic_inc_return(&binder_last_id);
2786 char *secctx = NULL;
2787 u32 secctx_sz = 0;
2781 2788
2782 e = binder_transaction_log_add(&binder_transaction_log);2789 e = binder_transaction_log_add(&binder_transaction_log);
2783 e->debug_id = t_debug_id;2790 e->debug_id = t_debug_id;
@@ -3020,6 +3027,20 @@ static void binder_transaction(struct binder_proc *proc, · 236 unmodified lines
3020 t->flags = tr->flags;3027 t->flags = tr->flags;
3021 t->priority = task_nice(current);3028 t->priority = task_nice(current);
3022 3029
3030 if (target_node && target_node->txn_security_ctx) {
3031 u32 secid;
3032
3033 security_task_getsecid(proc->tsk, &secid);
3034 ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
3035 if (ret) {
3036 return_error = BR_FAILED_REPLY;
3037 return_error_param = ret;
3038 return_error_line = __LINE__;
3039 goto err_get_secctx_failed;
3040 }
3041 extra_buffers_size += ALIGN(secctx_sz, sizeof(u64));
3042 }
3043
3023 trace_binder_transaction(reply, t, target_node);3044 trace_binder_transaction(reply, t, target_node);
3024 3045
3025 t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,3046 t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
@@ -3036,6 +3057,19 @@ static void binder_transaction(struct binder_proc *proc, · 10 unmodified lines
3036 t->buffer = NULL;3057 t->buffer = NULL;
3037 goto err_binder_alloc_buf_failed;3058 goto err_binder_alloc_buf_failed;
3038 }3059 }
3060 if (secctx) {
3061 size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
3062 ALIGN(tr->offsets_size, sizeof(void *)) +
3063 ALIGN(extra_buffers_size, sizeof(void *)) -
3064 ALIGN(secctx_sz, sizeof(u64));
3065 char *kptr = t->buffer->data + buf_offset;
3066
3067 t->security_ctx = (uintptr_t)kptr +
3068 binder_alloc_get_user_buffer_offset(&target_proc->alloc);
3069 memcpy(kptr, secctx, secctx_sz);
3070 security_release_secctx(secctx, secctx_sz);
3071 secctx = NULL;
3072 }
3039 t->buffer->debug_id = t->debug_id;3073 t->buffer->debug_id = t->debug_id;
3040 t->buffer->transaction = t;3074 t->buffer->transaction = t;
3041 t->buffer->target_node = target_node;3075 t->buffer->target_node = target_node;
@@ -3305,6 +3339,9 @@ err_copy_data_failed: · 263 unmodified lines
3305 t->buffer->transaction = NULL;3339 t->buffer->transaction = NULL;
3306 binder_alloc_free_buf(&target_proc->alloc, t->buffer);3340 binder_alloc_free_buf(&target_proc->alloc, t->buffer);
3307err_binder_alloc_buf_failed:3341err_binder_alloc_buf_failed:
3342 if (secctx)
3343 security_release_secctx(secctx, secctx_sz);
3344err_get_secctx_failed:
3308 kfree(tcomplete);3345 kfree(tcomplete);
3309 binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);3346 binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
3310err_alloc_tcomplete_failed:3347err_alloc_tcomplete_failed:
@@ -4036,11 +4073,13 @@ retry: · 725 unmodified lines
4036 4073
4037 while (1) {4074 while (1) {
4038 uint32_t cmd;4075 uint32_t cmd;
4039 struct binder_transaction_data tr;4076 struct binder_transaction_data_secctx tr;
4077 struct binder_transaction_data *trd = &tr.transaction_data;
4040 struct binder_work *w = NULL;4078 struct binder_work *w = NULL;
4041 struct list_head *list = NULL;4079 struct list_head *list = NULL;
4042 struct binder_transaction *t = NULL;4080 struct binder_transaction *t = NULL;
4043 struct binder_thread *t_from;4081 struct binder_thread *t_from;
4082 size_t trsize = sizeof(*trd);
4044 4083
4045 binder_inner_proc_lock(proc);4084 binder_inner_proc_lock(proc);
4046 if (!binder_worklist_empty_ilocked(&thread->todo))4085 if (!binder_worklist_empty_ilocked(&thread->todo))
@@ -4240,8 +4279,8 @@ retry: · 193 unmodified lines
4240 if (t->buffer->target_node) {4279 if (t->buffer->target_node) {
4241 struct binder_node *target_node = t->buffer->target_node;4280 struct binder_node *target_node = t->buffer->target_node;
4242 4281
4243 tr.target.ptr = target_node->ptr;4282 trd->target.ptr = target_node->ptr;
4244 tr.cookie = target_node->cookie;4283 trd->cookie = target_node->cookie;
4245 t->saved_priority = task_nice(current);4284 t->saved_priority = task_nice(current);
4246 if (t->priority < target_node->min_priority &&4285 if (t->priority < target_node->min_priority &&
4247 !(t->flags & TF_ONE_WAY))4286 !(t->flags & TF_ONE_WAY))
@@ -4251,22 +4290,23 @@ retry: · 3 unmodified lines
4251 binder_set_nice(target_node->min_priority);4290 binder_set_nice(target_node->min_priority);
4252 cmd = BR_TRANSACTION;4291 cmd = BR_TRANSACTION;
4253 } else {4292 } else {
4254 tr.target.ptr = 0;4293 trd->target.ptr = 0;
4255 tr.cookie = 0;4294 trd->cookie = 0;
4256 cmd = BR_REPLY;4295 cmd = BR_REPLY;
4257 }4296 }
4258 tr.code = t->code;4297 trd->code = t->code;
4259 tr.flags = t->flags;4298 trd->flags = t->flags;
4260 tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);4299 trd->sender_euid = from_kuid(current_user_ns(), t->sender_euid);
4261 4300
4262 t_from = binder_get_txn_from(t);4301 t_from = binder_get_txn_from(t);
4263 if (t_from) {4302 if (t_from) {
4264 struct task_struct *sender = t_from->proc->tsk;4303 struct task_struct *sender = t_from->proc->tsk;
4265 4304
4266 tr.sender_pid = task_tgid_nr_ns(sender,4305 trd->sender_pid =
4267 task_active_pid_ns(current));4306 task_tgid_nr_ns(sender,
4307 task_active_pid_ns(current));
4268 } else {4308 } else {
4269 tr.sender_pid = 0;4309 trd->sender_pid = 0;
4270 }4310 }
4271 4311
4272 ret = binder_apply_fd_fixups(t);4312 ret = binder_apply_fd_fixups(t);
@@ -4297,15 +4337,20 @@ retry: · 24 unmodified lines
4297 }4337 }
4298 continue;4338 continue;
4299 }4339 }
4300 tr.data_size = t->buffer->data_size;4340 trd->data_size = t->buffer->data_size;
4301 tr.offsets_size = t->buffer->offsets_size;4341 trd->offsets_size = t->buffer->offsets_size;
4302 tr.data.ptr.buffer = (binder_uintptr_t)4342 trd->data.ptr.buffer = (binder_uintptr_t)
4303 ((uintptr_t)t->buffer->data +4343 ((uintptr_t)t->buffer->data +
4304 binder_alloc_get_user_buffer_offset(&proc->alloc));4344 binder_alloc_get_user_buffer_offset(&proc->alloc));
4305 tr.data.ptr.offsets = tr.data.ptr.buffer +4345 trd->data.ptr.offsets = trd->data.ptr.buffer +
4306 ALIGN(t->buffer->data_size,4346 ALIGN(t->buffer->data_size,
4307 sizeof(void *));4347 sizeof(void *));
4308 4348
4349 tr.secctx = t->security_ctx;
4350 if (t->security_ctx) {
4351 cmd = BR_TRANSACTION_SEC_CTX;
4352 trsize = sizeof(tr);
4353 }
4309 if (put_user(cmd, (uint32_t __user *)ptr)) {4354 if (put_user(cmd, (uint32_t __user *)ptr)) {
4310 if (t_from)4355 if (t_from)
4311 binder_thread_dec_tmpref(t_from);4356 binder_thread_dec_tmpref(t_from);
@@ -4316,7 +4361,7 @@ retry: · 4 unmodified lines
4316 return -EFAULT;4361 return -EFAULT;
4317 }4362 }
4318 ptr += sizeof(uint32_t);4363 ptr += sizeof(uint32_t);
4319 if (copy_to_user(ptr, &tr, sizeof(tr))) {4364 if (copy_to_user(ptr, &tr, trsize)) {
4320 if (t_from)4365 if (t_from)
4321 binder_thread_dec_tmpref(t_from);4366 binder_thread_dec_tmpref(t_from);
4322 4367
@@ -4325,7 +4370,7 @@ retry: · 2 unmodified lines
4325 4370
4326 return -EFAULT;4371 return -EFAULT;
4327 }4372 }
4328 ptr += sizeof(tr);4373 ptr += trsize;
4329 4374
4330 trace_binder_transaction_received(t);4375 trace_binder_transaction_received(t);
4331 binder_stat_br(proc, thread, cmd);4376 binder_stat_br(proc, thread, cmd);
@@ -4333,16 +4378,18 @@ retry: · 1 unmodified line
4333 "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",4378 "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
4334 proc->pid, thread->pid,4379 proc->pid, thread->pid,
4335 (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :4380 (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
4336 "BR_REPLY",4381 (cmd == BR_TRANSACTION_SEC_CTX) ?
4382 "BR_TRANSACTION_SEC_CTX" : "BR_REPLY",
4337 t->debug_id, t_from ? t_from->proc->pid : 0,4383 t->debug_id, t_from ? t_from->proc->pid : 0,
4338 t_from ? t_from->pid : 0, cmd,4384 t_from ? t_from->pid : 0, cmd,
4339 t->buffer->data_size, t->buffer->offsets_size,4385 t->buffer->data_size, t->buffer->offsets_size,
4340 (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);4386 (u64)trd->data.ptr.buffer,
4387 (u64)trd->data.ptr.offsets);
4341 4388
4342 if (t_from)4389 if (t_from)
4343 binder_thread_dec_tmpref(t_from);4390 binder_thread_dec_tmpref(t_from);
4344 t->buffer->allow_user_free = 1;4391 t->buffer->allow_user_free = 1;
4345 if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {4392 if (cmd != BR_REPLY && !(t->flags & TF_ONE_WAY)) {
4346 binder_inner_proc_lock(thread->proc);4393 binder_inner_proc_lock(thread->proc);
4347 t->to_parent = thread->transaction_stack;4394 t->to_parent = thread->transaction_stack;
4348 t->to_thread = thread;4395 t->to_thread = thread;
@@ -4690,7 +4737,8 @@ out: · 341 unmodified lines
4690 return ret;4737 return ret;
4691}4738}
4692 4739
4693static int binder_ioctl_set_ctx_mgr(struct file *filp)4740static int binder_ioctl_set_ctx_mgr(struct file *filp,
4741 struct flat_binder_object *fbo)
4694{4742{
4695 int ret = 0;4743 int ret = 0;
4696 struct binder_proc *proc = filp->private_data;4744 struct binder_proc *proc = filp->private_data;
@@ -4719,7 +4767,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) · 22 unmodified lines
4719 } else {4767 } else {
4720 context->binder_context_mgr_uid = curr_euid;4768 context->binder_context_mgr_uid = curr_euid;
4721 }4769 }
4722 new_node = binder_new_node(proc, NULL);4770 new_node = binder_new_node(proc, fbo);
4723 if (!new_node) {4771 if (!new_node) {
4724 ret = -ENOMEM;4772 ret = -ENOMEM;
4725 goto out;4773 goto out;
@@ -4842,8 +4890,20 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) · 116 unmodified lines
4842 binder_inner_proc_unlock(proc);4890 binder_inner_proc_unlock(proc);
4843 break;4891 break;
4844 }4892 }
4893 case BINDER_SET_CONTEXT_MGR_EXT: {
4894 struct flat_binder_object fbo;
4895
4896 if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {
4897 ret = -EINVAL;
4898 goto err;
4899 }
4900 ret = binder_ioctl_set_ctx_mgr(filp, &fbo);
4901 if (ret)
4902 goto err;
4903 break;
4904 }
4845 case BINDER_SET_CONTEXT_MGR:4905 case BINDER_SET_CONTEXT_MGR:
4846 ret = binder_ioctl_set_ctx_mgr(filp);4906 ret = binder_ioctl_set_ctx_mgr(filp, NULL);
4847 if (ret)4907 if (ret)
4848 goto err;4908 goto err;
4849 break;4909 break;
include/uapi/linux/android/binder.h+19−0
@@ -41,6 +41,14 @@ enum { · 40 unmodified lines
41enum {41enum {
42 FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,42 FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
43 FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,43 FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
44
45 /**
46 * @FLAT_BINDER_FLAG_TXN_SECURITY_CTX: request security contexts
47 *
48 * Only when set, causes senders to include their security
49 * context
50 */
51 FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
44};52};
45 53
46#ifdef BINDER_IPC_32BIT54#ifdef BINDER_IPC_32BIT
@@ -218,6 +226,7 @@ struct binder_node_info_for_ref { · 171 unmodified lines
218#define BINDER_VERSION _IOWR('b', 9, struct binder_version)226#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
219#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)227#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
220#define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref)228#define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref)
229#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object)
221 230
222/*231/*
223 * NOTE: Two special error codes you should check for when calling232 * NOTE: Two special error codes you should check for when calling
@@ -276,6 +285,11 @@ struct binder_transaction_data { · 52 unmodified lines
276 } data;285 } data;
277};286};
278 287
288struct binder_transaction_data_secctx {
289 struct binder_transaction_data transaction_data;
290 binder_uintptr_t secctx;
291};
292
279struct binder_transaction_data_sg {293struct binder_transaction_data_sg {
280 struct binder_transaction_data transaction_data;294 struct binder_transaction_data transaction_data;
281 binder_size_t buffers_size;295 binder_size_t buffers_size;
@@ -311,6 +325,11 @@ enum binder_driver_return_protocol { · 29 unmodified lines
311 BR_OK = _IO('r', 1),325 BR_OK = _IO('r', 1),
312 /* No parameters! */326 /* No parameters! */
313 327
328 BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
329 struct binder_transaction_data_secctx),
330 /*
331 * binder_transaction_data_secctx: the received command.
332 */
314 BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),333 BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
315 BR_REPLY = _IOR('r', 3, struct binder_transaction_data),334 BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
316 /*335 /*