Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2498444imu; Tue, 6 Nov 2018 16:03:52 -0800 (PST) X-Google-Smtp-Source: AJdET5fQV/e39GJDgyAtAWH3YKj8PlAettmXa3DWCVAM4tgB7BTol0Gp1vgzg9f+jJ9aJyhsvwfE X-Received: by 2002:a17:902:4165:: with SMTP id e92-v6mr28863551pld.209.1541549032473; Tue, 06 Nov 2018 16:03:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1541549032; cv=none; d=google.com; s=arc-20160816; b=GIW4+5lBb6MCupiqhcyU3/HVb4MqlTdDOOTw4RfA9YmSvbOHk6Ip411pB3xq68nGS5 vaNS/BNXG2N2+hp3FUbgknmTu0q8N4l20bwXXPR04aulhYj6t5GIF7Qjtj8lmEnrHu1U 84+gNaOzsG0EzcrzJPpJU4h9oFRr9VDHsiF0FAa/i5aZn3XyktW7TjUI75a2TMMrV6AZ GZY9kSvVIdYJVf4QA7Zjw9zkhioq50VWHBDGxt2TQVWCxMkH3T3LA3GWtWnJgSFVVHJV 9oEXP3phxC4Kz7JqTXtiLA/ct80o57ggogaRpIC8Ezwl+TZE/HH06zP3C+rWhYMyXS0w 3A4w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=La2xAe9jd3uC28Fhz2DfVrF3HqHgtVXfdg5RQNp/Bkw=; b=klIYndiQmNfNc1j8YdBH+mYgpbGfoDFdk9oWvXVzE41O31yIv5GCSLS8cRLW+mKyzy 8/Anivl0bgLH1e4jDnpFExeW/YuJMiTFJjHZOVLwOZHO9PUBNn4Ieu7KYVNWSBeb/0uK nlWmZWp2sz3Yo9fYLzS81ZFtBYEqtjMQLlabjVo96GCKvYbYFMCOrUZXo6BpJFxRnlYn 7rvG2zwkC01VEqLTVQcOJPeOMO+2KboFmsnk9xbqIZepy+tcCrMN0vvMm+ndJORAwgGU DtcyY/lPQoOLlgYk9BTHM2KQCVUp71dYU5nvgUeIB7gFc3/rAbyycvJXCRrjFldOL08D gtWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@android.com header.s=20161025 header.b=n2aF9W7y; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=android.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f1-v6si32584818pfg.121.2018.11.06.16.03.36; Tue, 06 Nov 2018 16:03:52 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@android.com header.s=20161025 header.b=n2aF9W7y; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=android.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388405AbeKGJXh (ORCPT + 99 others); Wed, 7 Nov 2018 04:23:37 -0500 Received: from mail-pl1-f193.google.com ([209.85.214.193]:36162 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727292AbeKGJXg (ORCPT ); Wed, 7 Nov 2018 04:23:36 -0500 Received: by mail-pl1-f193.google.com with SMTP id w24-v6so6977753plq.3 for ; Tue, 06 Nov 2018 15:55:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=La2xAe9jd3uC28Fhz2DfVrF3HqHgtVXfdg5RQNp/Bkw=; b=n2aF9W7y4wYMFQYWfd/NikkJ2CPl2/+c+jpmUpwLyL5SPpiEcyAblE96uC18H/O/Mi 9M0h26n4NsXxznUy2gDIC0gYRjUFDv7jTp0PnQKRBoUiLIwqf22BXy8hYUwM94BWNJX/ cVuuObOz17c18PDZ3aJ7d/yMnURFha6zqg+W8MLLt7bEysFMOhUcLevzIuOclwyKMGlf cs96p7/9r+tlTfBGEzVxrIvThS6RRYW3iliVqRnd/3Fw+q9r3CnU5kkgczyd85u+DLkP f494vWHy5gP4wSzgWMPZZnSVFOeu6K3gZLCVaCXG7crqApNPH70Mohrttxlo/gTe2u1N kPQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=La2xAe9jd3uC28Fhz2DfVrF3HqHgtVXfdg5RQNp/Bkw=; b=gdqyhHjy/dSvncD4TVg0QTTW3TU5de0glZrA/0cOXoQvd/6zmH3Yg0aZIjZFraUj/J YbKUVfCEGPgpS+XvhABQGsVU4CXq6aZ8UHRs89OdgX2GassIokCNBuUZGtxvEL23Vw6f eukW5iuj07XhLUPA6Yi4fQBk7SVYOTJgT2Ldtw+JkZT70xHn3EBqyYqiqaEJ+B9/I25T z2MPPtb86MtsxAJoWvIUhblAT+xBIkVxhSTv4o2S9X8NBjFjYty2nbpJFmVrI4vOGDSH YjIuiMmWn5tB5a2HNiz7jVDiyx7HsRiV354hlRnB4R8SVby6FVBwj9H3FxXm1JaJb4Hh dzbg== X-Gm-Message-State: AGRZ1gKiuwrPQpVQtDGNWGJcIhvAWH5sIeaSrrQgLV3Fiz1zMxPww0/M rENVq354qkICIEWUfWd15lGluA== X-Received: by 2002:a17:902:be07:: with SMTP id r7-v6mr20093798pls.137.1541548550077; Tue, 06 Nov 2018 15:55:50 -0800 (PST) Received: from ava-linux2.mtv.corp.google.com ([2620:0:1000:1601:f5a1:2b8d:9c84:99b]) by smtp.googlemail.com with ESMTPSA id p62-v6sm67287329pfp.111.2018.11.06.15.55.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 06 Nov 2018 15:55:49 -0800 (PST) From: Todd Kjos X-Google-Original-From: Todd Kjos To: tkjos@google.com, gregkh@linuxfoundation.org, arve@android.com, devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org, maco@google.com, stable@vger.kernel.org Cc: kernel-team@android.com Subject: [PATCH] binder: fix race that allows malicious free of live buffer Date: Tue, 6 Nov 2018 15:55:32 -0800 Message-Id: <20181106235532.171646-1-tkjos@google.com> X-Mailer: git-send-email 2.19.1.930.g4563a0d9d0-goog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Malicious code can attempt to free buffers using the BC_FREE_BUFFER ioctl to binder. There are protections against a user freeing a buffer while in use by the kernel, however there was a window where BC_FREE_BUFFER could be used to free a recently allocated buffer that was not completely initialized. This resulted in a use-after-free detected by KASAN with a malicious test program. This window is closed by setting the buffer's allow_user_free attribute to 0 when the buffer is allocated or when the user has previously freed it instead of waiting for the caller to set it. The problem was that when the struct buffer was recycled, allow_user_free was stale and set to 1 allowing a free to go through. Signed-off-by: Todd Kjos Acked-by: Arve Hjønnevåg --- drivers/android/binder.c | 21 ++++++++++++--------- drivers/android/binder_alloc.c | 16 ++++++---------- drivers/android/binder_alloc.h | 3 +-- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index cb30a524d16d8..9f1000d2a40c7 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2974,7 +2974,6 @@ static void binder_transaction(struct binder_proc *proc, t->buffer = NULL; goto err_binder_alloc_buf_failed; } - t->buffer->allow_user_free = 0; t->buffer->debug_id = t->debug_id; t->buffer->transaction = t; t->buffer->target_node = target_node; @@ -3510,14 +3509,18 @@ static int binder_thread_write(struct binder_proc *proc, buffer = binder_alloc_prepare_to_free(&proc->alloc, data_ptr); - if (buffer == NULL) { - binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n", - proc->pid, thread->pid, (u64)data_ptr); - break; - } - if (!buffer->allow_user_free) { - binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n", - proc->pid, thread->pid, (u64)data_ptr); + if (IS_ERR_OR_NULL(buffer)) { + if (PTR_ERR(buffer) == -EPERM) { + binder_user_error( + "%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n", + proc->pid, thread->pid, + (u64)data_ptr); + } else { + binder_user_error( + "%d:%d BC_FREE_BUFFER u%016llx no match\n", + proc->pid, thread->pid, + (u64)data_ptr); + } break; } binder_debug(BINDER_DEBUG_FREE_BUFFER, diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 64fd96eada31f..030c98f35cca7 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -151,16 +151,12 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked( else { /* * Guard against user threads attempting to - * free the buffer twice + * free the buffer when in use by kernel or + * after it's already been freed. */ - if (buffer->free_in_progress) { - binder_alloc_debug(BINDER_DEBUG_USER_ERROR, - "%d:%d FREE_BUFFER u%016llx user freed buffer twice\n", - alloc->pid, current->pid, - (u64)user_ptr); - return NULL; - } - buffer->free_in_progress = 1; + if (!buffer->allow_user_free) + return ERR_PTR(-EPERM); + buffer->allow_user_free = 0; return buffer; } } @@ -500,7 +496,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( rb_erase(best_fit, &alloc->free_buffers); buffer->free = 0; - buffer->free_in_progress = 0; + buffer->allow_user_free = 0; binder_insert_allocated_buffer_locked(alloc, buffer); binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd got %pK\n", diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 9ef64e5638566..fb3238c74c8a8 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -50,8 +50,7 @@ struct binder_buffer { unsigned free:1; unsigned allow_user_free:1; unsigned async_transaction:1; - unsigned free_in_progress:1; - unsigned debug_id:28; + unsigned debug_id:29; struct binder_transaction *transaction; -- 2.19.1.930.g4563a0d9d0-goog