Received: by 10.223.185.116 with SMTP id b49csp4996973wrg; Wed, 7 Mar 2018 04:49:30 -0800 (PST) X-Google-Smtp-Source: AG47ELvIfSlTgCoexlstRinPouKX9ViqkNAqp45l72SadsHJ0jqdRG3RPQ3HKWvlXRssw1zAChHC X-Received: by 10.99.51.74 with SMTP id z71mr17751812pgz.272.1520426969931; Wed, 07 Mar 2018 04:49:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520426969; cv=none; d=google.com; s=arc-20160816; b=Zkg2w/UwhbFQ3/mh3TFYUQrSNSrR5DP75WCnHw0IGex8eniE3r1uLj1EPm4ZcQ1+RV FGuHB72iPEshEf4GblwuRZyhbhpvaL5I0xAxZi4zeGWXcAl11OrKk6Fwswi7GTO5ciGV oNAsKZlIt0xWEAoRU5TT1O6qjwB+T5leb9eteFNXTYmhcy4U4Bbts+8+SxKqqQzbWwk4 s+OVkzJoTGdaIlVaHl5FXFrs0AKODVTC/z3dkDKHTpYWjU44QrJ/PBJ8j9AsHlLuH/OM SfHsdkbx24wQohXNI/t+m6VI/moW0M0MTeXrtk7rMHv0OkMNxs/VVCp43cGRCCbrop4s OJnw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=JJAzIp9c+FdZH0Q7ooLwuveAf/zyIWBvUArSVtuaELE=; b=miEy8HDDNEjczNqHwLxk1hDcrkdHIAAJCbg1Vbrdz9kORKyTiX+pJPzJtPlXAQcBBN 9vulxnOazfQXDzLf0vyjyKcp4uSz+N6hAo7I9izoXjemVCkVL7ugJ3e+rkaBpvv7tcXY 2S24osPV7wQ4fr/OL4ohkrKJNAts5U6xJGPl7J0jnfOXuqo8AT7YmG6dKUCgdJ4jyQir zz8muXVhjNCAFrxjeAvRENmyx3f5w3xwRO1JBJAFJ/ml6+SPD/3vSm4sLYLQNsYE3bCc w/3/UevB4pMpkP/GnDjrMq5wSsIqSTbvtsfWNt1nRPXb7DgjEu8RtHHmDqrBO80pMKSM 3tfQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ursulin-net.20150623.gappssmtp.com header.s=20150623 header.b=Wer0K6tx; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e93-v6si12779729plk.159.2018.03.07.04.49.15; Wed, 07 Mar 2018 04:49:29 -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=@ursulin-net.20150623.gappssmtp.com header.s=20150623 header.b=Wer0K6tx; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754286AbeCGMre (ORCPT + 99 others); Wed, 7 Mar 2018 07:47:34 -0500 Received: from mail-wr0-f196.google.com ([209.85.128.196]:45931 "EHLO mail-wr0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751150AbeCGMr2 (ORCPT ); Wed, 7 Mar 2018 07:47:28 -0500 Received: by mail-wr0-f196.google.com with SMTP id p104so2021226wrc.12 for ; Wed, 07 Mar 2018 04:47:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ursulin-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=JJAzIp9c+FdZH0Q7ooLwuveAf/zyIWBvUArSVtuaELE=; b=Wer0K6txryeDuK221ttlD78sCl4z5GSXw7vzv6/wYVMMBjNSKwJviocv+6HOobS7oV eKYs0bpGci+zPrh/kRhcKmSQsl6Z1v48abPF/w+5VMTKDjjON15X0bRpBE1G1WHnMFsT UwMBdLG8E+XLV7HyyduxDMJxT9dD6oUAqMytFZnZG4o3iQvWy7JPtYOsZKt2HXLzXGwv 088HRiQkMryIxbpYiRLyyrZ/OPj3IzsaOZx6tZOvglMbsuzxC7bNMrV4l5CzjVIq0owX AQM81xSV/v3OYKEFfqeQN6WOJhrwWO0UZ9nZvPHWwS3nRR4PFnIL83tYw+Lw4CNg0HeI 5DtA== 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:in-reply-to :references; bh=JJAzIp9c+FdZH0Q7ooLwuveAf/zyIWBvUArSVtuaELE=; b=WfWgC/Q9F6CMyyR9U59rw8fKZdJ7a9rSFRI1oJqjft9H5ClxRmWl+YSxVb/QqzQSHF 94CnNPG6Be6M9vpYfq7vZB+h2yBkMJdjkG8PfFf8CdL+6AAsRQkpmFy9uPkVOXpw+EkT AxRJa8aRmkvbXXy6c1OMCqaN/2FOzhvAxx38DGynSfw+lWgwoMIEDWaiT798VpLeSwoi BZjsiQk7XXdN+zsZdVlM3KoUuviywGUI7rNPIDhnLvm9L0JSwIzADrqXGe4bjHTyAhbT WxtpOsWwmmuGbgsFM3fqHIgYSXg7pjENOeS8TtxyBzaAcLBVHi14QwzjBJ84NrhWTo7C 30lA== X-Gm-Message-State: APf1xPCo6h6w5a2PL9SWH/4p2OtFaLhT45WaXClkEGipuYYPW9hdGsg1 pVGCLs4iaY3lJMDuKWtoRFKW8E15 X-Received: by 10.223.173.18 with SMTP id p18mr20461565wrc.29.1520426847248; Wed, 07 Mar 2018 04:47:27 -0800 (PST) Received: from localhost.localdomain ([95.146.144.186]) by smtp.gmail.com with ESMTPSA id x78sm24325756wmd.2.2018.03.07.04.47.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Mar 2018 04:47:26 -0800 (PST) From: Tvrtko Ursulin X-Google-Original-From: Tvrtko Ursulin To: linux-kernel@vger.kernel.org Cc: Tvrtko Ursulin , Bart Van Assche , Hannes Reinecke , Johannes Thumshirn , Jens Axboe Subject: [PATCH 1/6] lib/scatterlist: Tidy types and fix overflow checking in sgl_alloc_order Date: Wed, 7 Mar 2018 12:47:07 +0000 Message-Id: <20180307124712.14963-2-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180307124712.14963-1-tvrtko.ursulin@linux.intel.com> References: <20180307124712.14963-1-tvrtko.ursulin@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tvrtko Ursulin There are several issues in sgl_alloc_order and accompanying APIs: 1. sgl_alloc_order explicitly takes a 64-bit length (unsigned long long) but then rejects it in overflow checking if greater than 4GiB allocation was requested. This is a consequence of using unsigned int for the right hand side condition which then natuarally overflows when shifted left, earlier than nent otherwise would. Fix is to promote the right hand side of the conditional to unsigned long. It is also not useful to allow for 64-bit lenght on 32-bit platforms so I have changed this type to a natural unsigned long. Like this it changes size naturally depending on the architecture. 2. elem_len should not be explicitly sized u32 but unsigned int, to match the underlying struct scatterlist nents type. Same for the nent_p output parameter type. I renamed this to chunk_len and consolidated its use throughout the function. 3. Eliminated nalloc local by re-arranging the code a bit. 4. Tidied types in other helpers, replacing int with unsigned int when passing in back the nents returned from sgl_alloc_order. Again, this is to match the struct scatterlist underlying types. Signed-off-by: Tvrtko Ursulin Cc: Bart Van Assche Cc: Hannes Reinecke Cc: Johannes Thumshirn Cc: Jens Axboe --- include/linux/scatterlist.h | 13 ++++++----- lib/scatterlist.c | 54 ++++++++++++++++++++++++--------------------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 22b2131bcdcd..2144de41ee04 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -277,13 +277,14 @@ int sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages, unsigned long size, gfp_t gfp_mask); #ifdef CONFIG_SGL_ALLOC -struct scatterlist *sgl_alloc_order(unsigned long long length, - unsigned int order, bool chainable, - gfp_t gfp, unsigned int *nent_p); -struct scatterlist *sgl_alloc(unsigned long long length, gfp_t gfp, +struct scatterlist *sgl_alloc_order(unsigned long length, unsigned int order, + bool chainable, gfp_t gfp, + unsigned int *nent_p); +struct scatterlist *sgl_alloc(unsigned long length, gfp_t gfp, unsigned int *nent_p); -void sgl_free_n_order(struct scatterlist *sgl, int nents, int order); -void sgl_free_order(struct scatterlist *sgl, int order); +void sgl_free_n_order(struct scatterlist *sgl, unsigned int nents, + unsigned int order); +void sgl_free_order(struct scatterlist *sgl, unsigned int order); void sgl_free(struct scatterlist *sgl); #endif /* CONFIG_SGL_ALLOC */ diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 53728d391d3a..d61c025e38b4 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -487,48 +487,51 @@ EXPORT_SYMBOL(sg_alloc_table_from_pages); * * Returns: A pointer to an initialized scatterlist or %NULL upon failure. */ -struct scatterlist *sgl_alloc_order(unsigned long long length, - unsigned int order, bool chainable, - gfp_t gfp, unsigned int *nent_p) +struct scatterlist *sgl_alloc_order(unsigned long length, unsigned int order, + bool chainable, gfp_t gfp, + unsigned int *nent_p) { + unsigned int chunk_len = PAGE_SIZE << order; struct scatterlist *sgl, *sg; - struct page *page; - unsigned int nent, nalloc; - u32 elem_len; + unsigned int nent; + + nent = round_up(length, chunk_len) >> (PAGE_SHIFT + order); - nent = round_up(length, PAGE_SIZE << order) >> (PAGE_SHIFT + order); /* Check for integer overflow */ - if (length > (nent << (PAGE_SHIFT + order))) + if (length > ((unsigned long)nent << (PAGE_SHIFT + order))) return NULL; - nalloc = nent; + + if (nent_p) + *nent_p = nent; + if (chainable) { /* Check for integer overflow */ - if (nalloc + 1 < nalloc) + if (nent == UINT_MAX) return NULL; - nalloc++; + nent++; } - sgl = kmalloc_array(nalloc, sizeof(struct scatterlist), + + sgl = kmalloc_array(nent, sizeof(struct scatterlist), (gfp & ~GFP_DMA) | __GFP_ZERO); if (!sgl) return NULL; - sg_init_table(sgl, nalloc); + sg_init_table(sgl, nent); sg = sgl; while (length) { - elem_len = min_t(u64, length, PAGE_SIZE << order); - page = alloc_pages(gfp, order); + struct page *page = alloc_pages(gfp, order); + if (!page) { sgl_free(sgl); return NULL; } - sg_set_page(sg, page, elem_len, 0); - length -= elem_len; + chunk_len = min_t(unsigned long, length, chunk_len); + sg_set_page(sg, page, chunk_len, 0); + length -= chunk_len; sg = sg_next(sg); } - WARN_ONCE(length, "length = %lld\n", length); - if (nent_p) - *nent_p = nent; + WARN_ONCE(length, "length = %ld\n", length); return sgl; } EXPORT_SYMBOL(sgl_alloc_order); @@ -541,7 +544,7 @@ EXPORT_SYMBOL(sgl_alloc_order); * * Returns: A pointer to an initialized scatterlist or %NULL upon failure. */ -struct scatterlist *sgl_alloc(unsigned long long length, gfp_t gfp, +struct scatterlist *sgl_alloc(unsigned long length, gfp_t gfp, unsigned int *nent_p) { return sgl_alloc_order(length, 0, false, gfp, nent_p); @@ -561,11 +564,12 @@ EXPORT_SYMBOL(sgl_alloc); * - All pages in a chained scatterlist can be freed at once by setting @nents * to a high number. */ -void sgl_free_n_order(struct scatterlist *sgl, int nents, int order) +void sgl_free_n_order(struct scatterlist *sgl, unsigned int nents, + unsigned int order) { struct scatterlist *sg; struct page *page; - int i; + unsigned int i; for_each_sg(sgl, sg, nents, i) { if (!sg) @@ -583,9 +587,9 @@ EXPORT_SYMBOL(sgl_free_n_order); * @sgl: Scatterlist with one or more elements * @order: Second argument for __free_pages() */ -void sgl_free_order(struct scatterlist *sgl, int order) +void sgl_free_order(struct scatterlist *sgl, unsigned int order) { - sgl_free_n_order(sgl, INT_MAX, order); + sgl_free_n_order(sgl, UINT_MAX, order); } EXPORT_SYMBOL(sgl_free_order); -- 2.14.1