Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751753AbdISMLZ (ORCPT ); Tue, 19 Sep 2017 08:11:25 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50430 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751497AbdISMLX (ORCPT ); Tue, 19 Sep 2017 08:11:23 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 1C9B6356F6 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=fweimer@redhat.com Subject: Re: [patch] mremap.2: Add description of old_size == 0 functionality To: Mike Kravetz , mtk.manpages@gmail.com Cc: linux-man@vger.kernel.org, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, Michal Hocko , Andrea Arcangeli , "Kirill A . Shutemov" , Vlastimil Babka , Anshuman Khandual , linux-mm@kvack.org References: <20170915213745.6821-1-mike.kravetz@oracle.com> From: Florian Weimer Message-ID: Date: Tue, 19 Sep 2017 14:11:19 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 19 Sep 2017 12:11:23 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3499 Lines: 98 On 09/18/2017 07:11 PM, Mike Kravetz wrote: > On 09/18/2017 06:45 AM, Florian Weimer wrote: >> On 09/15/2017 11:53 PM, Mike Kravetz wrote: >>> +If the value of \fIold_size\fP is zero, and \fIold_address\fP refers to >>> +a private anonymous mapping, then >>> +.BR mremap () >>> +will create a new mapping of the same pages. \fInew_size\fP >>> +will be the size of the new mapping and the location of the new mapping >>> +may be specified with \fInew_address\fP, see the description of >>> +.B MREMAP_FIXED >>> +below. If a new mapping is requested via this method, then the >>> +.B MREMAP_MAYMOVE >>> +flag must also be specified. This functionality is deprecated, and no >>> +new code should be written to use this feature. A better method of >>> +obtaining multiple mappings of the same private anonymous memory is via the >>> +.BR memfd_create() >>> +system call. >> >> Is there any particular reason to deprecate this? >> >> In glibc, we cannot use memfd_create and keep the file descriptor around because the application can close descriptors beneath us. >> >> (We might want to use alias mappings to avoid run-time code generation for PLT-less LD_AUDIT interceptors.) >> > > Hi Florian, > > When I brought up this mremap 'duplicate mapping' functionality on the mm > mail list, most developers were surprised. It seems this functionality exists > mostly 'by chance', and it was not really designed. It certainly was never > documented. There were suggestions to remove the functionality, which led > to my claim that it was being deprecated. However, in hindsight that may > have been too strong. This history is certainly a bit odd. > I can drop this wording, but would still like to suggest memfd_create as > the preferred method of creating duplicate mappings. It would be good if > others on Cc: could comment as well. mremap seems to work with non-anonymous mappings, too: #include #include #include #include #include #include #include /* Hopefully large enough to prevent crossing of a page boundary in the implementation. */ __attribute__ ((aligned (256), noclone, noinline, weak)) int callback (void) { return 17; } int main (void) { long pagesize = sysconf (_SC_PAGESIZE); if (pagesize < 0) err (1, "sysconf"); uintptr_t addr = (uintptr_t) &callback; addr = addr / pagesize * pagesize; printf ("old function address: %p\n", &callback); ptrdiff_t page_offset = (uintptr_t) &callback - addr; void *newaddr = mremap ((void *) addr, 0, pagesize, MREMAP_MAYMOVE); if (newaddr == MAP_FAILED) err (1, "mremap"); if (memcmp ((void *) addr, newaddr, pagesize) != 0) errx (1, "page contents differs"); int (*newfunc) (void) = newaddr + page_offset; printf ("new function address: %p\n", newfunc); if (newfunc () != 17) errx (1, "invalid return value from newfunc"); if (callback () != 17) errx (1, "invalid return value from callback"); return 0; } (The code needs adjustment for architectures where function pointers point to a descriptor and not the actual code.) This looks very useful for generating arbitrary callback wrappers without actual run-time code generation. memfd_create would not work for that. > Just curious, does glibc make use of this today? Or, is this just something > that you think may be useful. To my knowledge, we do not use this today. But it certainly looks very useful. Thanks, Florian