linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Todd Kjos <tkjos@google.com>,
	"Joel Fernandes (Google)" <joel@joelfernandes.org>
Subject: [PATCH 5.0 03/46] binder: create node flag to request senders security context
Date: Fri,  8 Mar 2019 13:49:36 +0100	[thread overview]
Message-ID: <20190308124902.462820025@linuxfoundation.org> (raw)
In-Reply-To: <20190308124902.257040783@linuxfoundation.org>

5.0-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Todd Kjos <tkjos@android.com>

commit ec74136ded792deed80780a2f8baf3521eeb72f9 upstream.

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.

Signed-off-by: Todd Kjos <tkjos@google.com>
Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 drivers/android/binder.c            |  106 ++++++++++++++++++++++++++++--------
 include/uapi/linux/android/binder.h |   19 ++++++
 2 files changed, 102 insertions(+), 23 deletions(-)

--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -329,6 +329,8 @@ struct binder_error {
  *                        (invariant after initialized)
  * @min_priority:         minimum scheduling priority
  *                        (invariant after initialized)
+ * @txn_security_ctx:     require sender's security context
+ *                        (invariant after initialized)
  * @async_todo:           list of async work items
  *                        (protected by @proc->inner_lock)
  *
@@ -365,6 +367,7 @@ struct binder_node {
 		 * invariant after initialization
 		 */
 		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
 		u8 min_priority;
 	};
 	bool has_async_transaction;
@@ -615,6 +618,7 @@ struct binder_transaction {
 	long	saved_priority;
 	kuid_t	sender_euid;
 	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
 	/**
 	 * @lock:  protects @from, @to_proc, and @to_thread
 	 *
@@ -1152,6 +1156,7 @@ static struct binder_node *binder_init_n
 	node->work.type = BINDER_WORK_NODE;
 	node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
 	node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+	node->txn_security_ctx = !!(flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX);
 	spin_lock_init(&node->lock);
 	INIT_LIST_HEAD(&node->work.entry);
 	INIT_LIST_HEAD(&node->async_todo);
@@ -2778,6 +2783,8 @@ static void binder_transaction(struct bi
 	binder_size_t last_fixup_min_off = 0;
 	struct binder_context *context = proc->context;
 	int t_debug_id = atomic_inc_return(&binder_last_id);
+	char *secctx = NULL;
+	u32 secctx_sz = 0;
 
 	e = binder_transaction_log_add(&binder_transaction_log);
 	e->debug_id = t_debug_id;
@@ -3020,6 +3027,20 @@ static void binder_transaction(struct bi
 	t->flags = tr->flags;
 	t->priority = task_nice(current);
 
+	if (target_node && target_node->txn_security_ctx) {
+		u32 secid;
+
+		security_task_getsecid(proc->tsk, &secid);
+		ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
+		if (ret) {
+			return_error = BR_FAILED_REPLY;
+			return_error_param = ret;
+			return_error_line = __LINE__;
+			goto err_get_secctx_failed;
+		}
+		extra_buffers_size += ALIGN(secctx_sz, sizeof(u64));
+	}
+
 	trace_binder_transaction(reply, t, target_node);
 
 	t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
@@ -3036,6 +3057,19 @@ static void binder_transaction(struct bi
 		t->buffer = NULL;
 		goto err_binder_alloc_buf_failed;
 	}
+	if (secctx) {
+		size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
+				    ALIGN(tr->offsets_size, sizeof(void *)) +
+				    ALIGN(extra_buffers_size, sizeof(void *)) -
+				    ALIGN(secctx_sz, sizeof(u64));
+		char *kptr = t->buffer->data + buf_offset;
+
+		t->security_ctx = (uintptr_t)kptr +
+		    binder_alloc_get_user_buffer_offset(&target_proc->alloc);
+		memcpy(kptr, secctx, secctx_sz);
+		security_release_secctx(secctx, secctx_sz);
+		secctx = NULL;
+	}
 	t->buffer->debug_id = t->debug_id;
 	t->buffer->transaction = t;
 	t->buffer->target_node = target_node;
@@ -3305,6 +3339,9 @@ err_copy_data_failed:
 	t->buffer->transaction = NULL;
 	binder_alloc_free_buf(&target_proc->alloc, t->buffer);
 err_binder_alloc_buf_failed:
+	if (secctx)
+		security_release_secctx(secctx, secctx_sz);
+err_get_secctx_failed:
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
@@ -4036,11 +4073,13 @@ retry:
 
 	while (1) {
 		uint32_t cmd;
-		struct binder_transaction_data tr;
+		struct binder_transaction_data_secctx tr;
+		struct binder_transaction_data *trd = &tr.transaction_data;
 		struct binder_work *w = NULL;
 		struct list_head *list = NULL;
 		struct binder_transaction *t = NULL;
 		struct binder_thread *t_from;
+		size_t trsize = sizeof(*trd);
 
 		binder_inner_proc_lock(proc);
 		if (!binder_worklist_empty_ilocked(&thread->todo))
@@ -4240,8 +4279,8 @@ retry:
 		if (t->buffer->target_node) {
 			struct binder_node *target_node = t->buffer->target_node;
 
-			tr.target.ptr = target_node->ptr;
-			tr.cookie =  target_node->cookie;
+			trd->target.ptr = target_node->ptr;
+			trd->cookie =  target_node->cookie;
 			t->saved_priority = task_nice(current);
 			if (t->priority < target_node->min_priority &&
 			    !(t->flags & TF_ONE_WAY))
@@ -4251,22 +4290,23 @@ retry:
 				binder_set_nice(target_node->min_priority);
 			cmd = BR_TRANSACTION;
 		} else {
-			tr.target.ptr = 0;
-			tr.cookie = 0;
+			trd->target.ptr = 0;
+			trd->cookie = 0;
 			cmd = BR_REPLY;
 		}
-		tr.code = t->code;
-		tr.flags = t->flags;
-		tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);
+		trd->code = t->code;
+		trd->flags = t->flags;
+		trd->sender_euid = from_kuid(current_user_ns(), t->sender_euid);
 
 		t_from = binder_get_txn_from(t);
 		if (t_from) {
 			struct task_struct *sender = t_from->proc->tsk;
 
-			tr.sender_pid = task_tgid_nr_ns(sender,
-							task_active_pid_ns(current));
+			trd->sender_pid =
+				task_tgid_nr_ns(sender,
+						task_active_pid_ns(current));
 		} else {
-			tr.sender_pid = 0;
+			trd->sender_pid = 0;
 		}
 
 		ret = binder_apply_fd_fixups(t);
@@ -4297,15 +4337,20 @@ retry:
 			}
 			continue;
 		}
-		tr.data_size = t->buffer->data_size;
-		tr.offsets_size = t->buffer->offsets_size;
-		tr.data.ptr.buffer = (binder_uintptr_t)
+		trd->data_size = t->buffer->data_size;
+		trd->offsets_size = t->buffer->offsets_size;
+		trd->data.ptr.buffer = (binder_uintptr_t)
 			((uintptr_t)t->buffer->data +
 			binder_alloc_get_user_buffer_offset(&proc->alloc));
-		tr.data.ptr.offsets = tr.data.ptr.buffer +
+		trd->data.ptr.offsets = trd->data.ptr.buffer +
 					ALIGN(t->buffer->data_size,
 					    sizeof(void *));
 
+		tr.secctx = t->security_ctx;
+		if (t->security_ctx) {
+			cmd = BR_TRANSACTION_SEC_CTX;
+			trsize = sizeof(tr);
+		}
 		if (put_user(cmd, (uint32_t __user *)ptr)) {
 			if (t_from)
 				binder_thread_dec_tmpref(t_from);
@@ -4316,7 +4361,7 @@ retry:
 			return -EFAULT;
 		}
 		ptr += sizeof(uint32_t);
-		if (copy_to_user(ptr, &tr, sizeof(tr))) {
+		if (copy_to_user(ptr, &tr, trsize)) {
 			if (t_from)
 				binder_thread_dec_tmpref(t_from);
 
@@ -4325,7 +4370,7 @@ retry:
 
 			return -EFAULT;
 		}
-		ptr += sizeof(tr);
+		ptr += trsize;
 
 		trace_binder_transaction_received(t);
 		binder_stat_br(proc, thread, cmd);
@@ -4333,16 +4378,18 @@ retry:
 			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
 			     proc->pid, thread->pid,
 			     (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
-			     "BR_REPLY",
+				(cmd == BR_TRANSACTION_SEC_CTX) ?
+				     "BR_TRANSACTION_SEC_CTX" : "BR_REPLY",
 			     t->debug_id, t_from ? t_from->proc->pid : 0,
 			     t_from ? t_from->pid : 0, cmd,
 			     t->buffer->data_size, t->buffer->offsets_size,
-			     (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);
+			     (u64)trd->data.ptr.buffer,
+			     (u64)trd->data.ptr.offsets);
 
 		if (t_from)
 			binder_thread_dec_tmpref(t_from);
 		t->buffer->allow_user_free = 1;
-		if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
+		if (cmd != BR_REPLY && !(t->flags & TF_ONE_WAY)) {
 			binder_inner_proc_lock(thread->proc);
 			t->to_parent = thread->transaction_stack;
 			t->to_thread = thread;
@@ -4690,7 +4737,8 @@ out:
 	return ret;
 }
 
-static int binder_ioctl_set_ctx_mgr(struct file *filp)
+static int binder_ioctl_set_ctx_mgr(struct file *filp,
+				    struct flat_binder_object *fbo)
 {
 	int ret = 0;
 	struct binder_proc *proc = filp->private_data;
@@ -4719,7 +4767,7 @@ static int binder_ioctl_set_ctx_mgr(stru
 	} else {
 		context->binder_context_mgr_uid = curr_euid;
 	}
-	new_node = binder_new_node(proc, NULL);
+	new_node = binder_new_node(proc, fbo);
 	if (!new_node) {
 		ret = -ENOMEM;
 		goto out;
@@ -4842,8 +4890,20 @@ static long binder_ioctl(struct file *fi
 		binder_inner_proc_unlock(proc);
 		break;
 	}
+	case BINDER_SET_CONTEXT_MGR_EXT: {
+		struct flat_binder_object fbo;
+
+		if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {
+			ret = -EINVAL;
+			goto err;
+		}
+		ret = binder_ioctl_set_ctx_mgr(filp, &fbo);
+		if (ret)
+			goto err;
+		break;
+	}
 	case BINDER_SET_CONTEXT_MGR:
-		ret = binder_ioctl_set_ctx_mgr(filp);
+		ret = binder_ioctl_set_ctx_mgr(filp, NULL);
 		if (ret)
 			goto err;
 		break;
--- a/include/uapi/linux/android/binder.h
+++ b/include/uapi/linux/android/binder.h
@@ -41,6 +41,14 @@ enum {
 enum {
 	FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
 	FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
+
+	/**
+	 * @FLAT_BINDER_FLAG_TXN_SECURITY_CTX: request security contexts
+	 *
+	 * Only when set, causes senders to include their security
+	 * context
+	 */
+	FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
 };
 
 #ifdef BINDER_IPC_32BIT
@@ -218,6 +226,7 @@ struct binder_node_info_for_ref {
 #define BINDER_VERSION			_IOWR('b', 9, struct binder_version)
 #define BINDER_GET_NODE_DEBUG_INFO	_IOWR('b', 11, struct binder_node_debug_info)
 #define BINDER_GET_NODE_INFO_FOR_REF	_IOWR('b', 12, struct binder_node_info_for_ref)
+#define BINDER_SET_CONTEXT_MGR_EXT	_IOW('b', 13, struct flat_binder_object)
 
 /*
  * NOTE: Two special error codes you should check for when calling
@@ -276,6 +285,11 @@ struct binder_transaction_data {
 	} data;
 };
 
+struct binder_transaction_data_secctx {
+	struct binder_transaction_data transaction_data;
+	binder_uintptr_t secctx;
+};
+
 struct binder_transaction_data_sg {
 	struct binder_transaction_data transaction_data;
 	binder_size_t buffers_size;
@@ -311,6 +325,11 @@ enum binder_driver_return_protocol {
 	BR_OK = _IO('r', 1),
 	/* No parameters! */
 
+	BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
+				      struct binder_transaction_data_secctx),
+	/*
+	 * binder_transaction_data_secctx: the received command.
+	 */
 	BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
 	BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
 	/*



  parent reply	other threads:[~2019-03-08 12:52 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-08 12:49 [PATCH 5.0 00/46] 5.0.1-stable review Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 01/46] cpufreq: Use struct kobj_attribute instead of struct global_attr Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 02/46] staging: erofs: fix mis-acted TAIL merging behavior Greg Kroah-Hartman
2019-03-08 12:49 ` Greg Kroah-Hartman [this message]
2019-03-08 12:49 ` [PATCH 5.0 04/46] USB: serial: option: add Telit ME910 ECM composition Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 05/46] USB: serial: cp210x: add ID for Ingenico 3070 Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 06/46] USB: serial: ftdi_sio: add ID for Hjelmslund Electronics USB485 Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 07/46] driver core: Postpone DMA tear-down until after devres release Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 08/46] staging: erofs: fix fast symlink w/o xattr when fs xattr is on Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 09/46] staging: erofs: fix memleak of inodes shared xattr array Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 10/46] staging: erofs: fix race of initializing xattrs of a inode at the same time Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 11/46] staging: erofs: fix illegal address access under memory pressure Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 12/46] staging: comedi: ni_660x: fix missing break in switch statement Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 13/46] staging: wilc1000: fix to set correct value for vif_num Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 14/46] staging: android: ion: fix sys heap pools gfp_flags Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 15/46] staging: android: ashmem: Dont call fallocate() with ashmem_mutex held Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 16/46] staging: android: ashmem: Avoid range_alloc() allocation " Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 17/46] ip6mr: Do not call __IP6_INC_STATS() from preemptible context Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 18/46] net: dsa: mv88e6xxx: add call to mv88e6xxx_ports_cmode_init to probe for new DSA framework Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 19/46] net: dsa: mv88e6xxx: handle unknown duplex modes gracefully in mv88e6xxx_port_set_duplex Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 20/46] net: dsa: mv8e6xxx: fix number of internal PHYs for 88E6x90 family Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 21/46] net: mscc: Enable all ports in QSGMII Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 22/46] net: sched: put back q.qlen into a single location Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 23/46] net-sysfs: Fix mem leak in netdev_register_kobject Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 24/46] qmi_wwan: Add support for Quectel EG12/EM12 Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 25/46] sctp: call iov_iter_revert() after sending ABORT Greg Kroah-Hartman
2019-03-08 12:49 ` [PATCH 5.0 26/46] sky2: Disable MSI on Dell Inspiron 1545 and Gateway P-79 Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 27/46] team: Free BPF filter when unregistering netdev Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 28/46] tipc: fix RDM/DGRAM connect() regression Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 29/46] x86/CPU/AMD: Set the CPB bit unconditionally on F17h Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 30/46] x86/boot/compressed/64: Do not read legacy ROM on EFI system Greg Kroah-Hartman
2019-03-10  6:10   ` hpa
2019-03-10  6:18     ` Greg Kroah-Hartman
2019-03-11  1:44       ` hpa
2019-03-12  9:50     ` Kirill A. Shutemov
2019-03-08 12:50 ` [PATCH 5.0 31/46] tracing: Fix event filters and triggers to handle negative numbers Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 32/46] xhci: tegra: Prevent error pointer dereference Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 33/46] usb: xhci: Fix for Enabling USB ROLE SWITCH QUIRK on INTEL_SUNRISEPOINT_LP_XHCI Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 34/46] applicom: Fix potential Spectre v1 vulnerabilities Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 35/46] alpha: wire up io_pgetevents system call Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 36/46] MIPS: irq: Allocate accurate order pages for irq stack Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 37/46] aio: Fix locking in aio_poll() Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 38/46] xtensa: fix get_wchan Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 39/46] gnss: sirf: fix premature wakeup interrupt enable Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 40/46] USB: serial: cp210x: fix GPIO in autosuspend Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 41/46] Revert "selftests: firmware: add CONFIG_FW_LOADER_USER_HELPER_FALLBACK to config" Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 42/46] Revert "selftests: firmware: remove use of non-standard diff -Z option" Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 43/46] selftests: firmware: fix verify_reqs() return value Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 44/46] Bluetooth: btrtl: Restore old logic to assume firmware is already loaded Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 45/46] Bluetooth: Fix locking in bt_accept_enqueue() for BH context Greg Kroah-Hartman
2019-03-08 12:50 ` [PATCH 5.0 46/46] exec: Fix mem leak in kernel_read_file Greg Kroah-Hartman
2019-03-08 16:06 ` [PATCH 5.0 00/46] 5.0.1-stable review Jon Hunter
2019-03-08 16:35   ` Greg Kroah-Hartman
2019-03-08 20:58 ` shuah
2019-03-09  6:53   ` Greg Kroah-Hartman
2019-03-09  7:10 ` Naresh Kamboju
2019-03-09  7:23   ` Greg Kroah-Hartman
2019-03-09 22:36 ` Guenter Roeck
2019-03-10  6:05   ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190308124902.462820025@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=joel@joelfernandes.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=tkjos@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).