From patchwork Tue Apr 13 08:40:02 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Johansen X-Patchwork-Id: 50050 X-Patchwork-Delegate: apw@canonical.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 7109AB7CF0 for ; Tue, 13 Apr 2010 18:40:16 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.69) (envelope-from ) id 1O1bfE-0005X2-Ti; Tue, 13 Apr 2010 09:40:08 +0100 Received: from adelie.canonical.com ([91.189.90.139]) by chlorine.canonical.com with esmtp (Exim 4.69) (envelope-from ) id 1O1bfC-0005Wk-GB for kernel-team@lists.ubuntu.com; Tue, 13 Apr 2010 09:40:06 +0100 Received: from hutte.canonical.com ([91.189.90.181]) by adelie.canonical.com with esmtp (Exim 4.69 #1 (Debian)) id 1O1bfC-0002EJ-Bb; Tue, 13 Apr 2010 09:40:06 +0100 Received: from [96.225.230.137] (helo=[192.168.1.4]) by hutte.canonical.com with esmtpsa (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1O1bfC-00047D-3R; Tue, 13 Apr 2010 09:40:06 +0100 Message-ID: <4BC42DE2.9020906@canonical.com> Date: Tue, 13 Apr 2010 01:40:02 -0700 From: John Johansen Organization: Canonical User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100404 Thunderbird/3.0.4 MIME-Version: 1.0 To: Stefan Bader Subject: Re: [PATCH 11/11] AppArmor: use the kernel shared workqueue to free vmalloc'ed dfas References: <1271142580-26555-1-git-send-email-john.johansen@canonical.com> <1271142580-26555-12-git-send-email-john.johansen@canonical.com> <4BC429CF.5060702@canonical.com> In-Reply-To: <4BC429CF.5060702@canonical.com> X-Enigmail-Version: 1.0.1 Cc: kernel-team@lists.ubuntu.com X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.9 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com On 04/13/2010 01:22 AM, Stefan Bader wrote: > Dunno, this looks a bit scary. Assuming the size of table is big enough to > contain a work struct, but is the struct really never touched again after > calling the worker function? > attached is a patch that adds the size condition tsize = tsize < sizeof(struct work_struct) ? sizeof(struct work_struct) : tsize; to the allocation path Acked-by: Andy Whitcroft AppArmor: use the kernel shared workqueue to free vmalloc'ed dfas AppArmor falls back to allocating dfas with vmalloc when memory becomes fragmented. However dfa life cycle is often dependent on credentials which can be freed during interrupt context. This can in cause the dfa to be freed during interrupt context, as well but vfree can not be used in interrupt context. So for dfas that are allocated with vmalloc delay freeing them to a later time by placing them on the kernel shared workqueue. Signed-off-by: John Johansen diff --git a/security/apparmor/match.c b/security/apparmor/match.c index afc2dd2..a3730e2 100644 --- a/security/apparmor/match.c +++ b/security/apparmor/match.c @@ -17,12 +17,26 @@ #include #include #include +#include #include #include #include "include/match.h" /** + * do_vfree - workqueue routine for freeing vmalloced memory + * @work: data to be freed + * + * The work_struct is overlayed to the data being freed, as at the point + * the work is scheduled the data is no longer valid, be its freeing + * needs to be delayed until safe. + */ +static void do_vfree(struct work_struct *work) +{ + vfree(work); +} + +/** * free_table - free a table allocated by unpack table * @table: table to unpack (MAYBE NULL) */ @@ -31,9 +45,14 @@ static void free_table(struct table_header *table) if (!table) return; - if (is_vmalloc_addr(table)) - vfree(table); - else + if (is_vmalloc_addr(table)) { + /* Data is no longer valid so just use the allocated space + * as the work_struct + */ + struct work_struct *work = (struct work_struct *) table; + INIT_WORK(work, do_vfree); + schedule_work(work); + } else kzfree(table); } @@ -75,6 +94,8 @@ static struct table_header *unpack_table(char *blob, size_t bsize) /* freed by free_table */ table = kmalloc(tsize, GFP_KERNEL | __GFP_NOWARN); if (!table) { + tsize = tsize < sizeof(struct work_struct) ? + sizeof(struct work_struct) : tsize; unmap_alias = 1; table = vmalloc(tsize); }