1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 /**
10  * \file mmap_anon.c
11  * \brief Provide a compatible anonymous space mapping function
12  */
13 
14 #include <stdio.h>
15 
16 #include <fcntl.h>
17 #include <sys/mman.h>
18 #include <unistd.h>
19 
20 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
21 #define MAP_ANONYMOUS MAP_ANON
22 #endif
23 
24 /*
25  * mmap() anonymous space, depending on the system's mmap() style. On systems
26  * that use the /dev/zero mapping idiom, zerofd will be set to the file descriptor
27  * of the opened /dev/zero.
28  */
29 
30  /**
31  * \brief mmap() anonymous space, depending on the system's mmap() style. On systems
32  * that use the /dev/zero mapping idiom, zerofd will be set to the file descriptor
33  * of the opened /dev/zero.
34  *
35  * \param addr address to map at.
36  * \param len number of bytes from addr to be mapped.
37  * \param prot protections (region accessibility).
38  * \param flags specifies the type of the mapped object.
39  * \param offset start mapping at byte offset.
40  * \param zerofd
41  * \return a pointer to the mapped region upon successful completion, -1 otherwise.
42  */
mmap_anon(void * addr,size_t len,int prot,int flags,off_t offset)43 void *mmap_anon(void *addr, size_t len, int prot, int flags, off_t offset)
44 {
45     void *result;
46 
47 #ifndef MAP_ANONYMOUS
48     int fd;
49 #endif
50 
51      /* From loader/ext.c:
52       * "Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap"
53       * Therefore we preserve the same behavior on all platforms, ie. no
54       * shared mappings of anon space (if the concepts are supported). */
55 #if defined(MAP_SHARED) && defined(MAP_PRIVATE)
56      flags = (flags & ~MAP_SHARED) | MAP_PRIVATE;
57 #endif /* defined(MAP_SHARED) && defined(MAP_PRIVATE) */
58 
59 #ifdef MAP_ANONYMOUS
60     /* BSD-style anonymous mapping */
61     result = mmap(addr, len, prot, flags | MAP_ANONYMOUS, -1, offset);
62 #else
63     /* SysV-style anonymous mapping */
64     fd = open("/dev/zero", O_RDWR);
65     if(fd < 0){
66         perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: ");
67         return NULL;
68     }
69 
70     result = mmap(addr, len, prot, flags, fd, offset);
71     close(fd);
72 #endif /* MAP_ANONYMOUS */
73 
74     return result;
75 }
76