Issue
I am not understanding the 'aligning allocated memory' part from the mprotect usage.
I am referring to the code example given on rel="nofollow noreferrer">http://linux.die.net/man/2/mprotect
char *p;
char c;
/* Allocate a buffer; it will have the default
protection of PROT_READ|PROT_WRITE. */
p = malloc(1024+PAGESIZE-1);
if (!p) {
perror("Couldn't malloc(1024)");
exit(errno);
}
/* Align to a multiple of PAGESIZE, assumed to be a power of two */
p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
c = p[666]; /* Read; ok */
p[666] = 42; /* Write; ok */
/* Mark the buffer read-only. */
if (mprotect(p, 1024, PROT_READ)) {
perror("Couldn't mprotect");
exit(errno);
}
For my understanding, I tried using a PAGESIZE of 16, and 0010 as address of p.
I ended up getting 0001 as the result of (((int) p + PAGESIZE-1) & ~(PAGESIZE-1))
.
Could you please clarify how this whole 'alignment' works?
Thanks,
Solution
Assuming that PAGESIZE
is a power of 2 (a requirement), an integral value x can be rounded down to a multiple of PAGESIZE
with (x & ~(PAGESIZE-1))
. Similarly, ((x + PAGESIZE-1) & ~(PAGESIZE-1))
will result in x rounded up to a multiple of PAGESIZE
.
For example, if PAGESIZE
is 16, then in binary with a 32-bit word:
00000000000000000000000000010000
PAGESIZE
00000000000000000000000000001111
PAGESIZE-1
11111111111111111111111111110000
~(PAGESIZE-1)
A bitwise-and (&) with the above value will clear the low 4 bits of the value, making it a multiple of 16.
That said, the code quoted in the description is from an old version of the manual page, and is not good because it wastes memory and does not work on 64-bit systems. It is better to use posix_memalign()
or memalign()
to obtain memory that is already properly aligned. The example on the current version of the mprotect()
manual page uses memalign()
. The advantage of posix_memalign()
is that it is part of the POSIX standard, and does not have different behavior on different systems like the older non-standard memalign()
.
Answered By - mark4o Answer Checked By - Willingham (WPSolving Volunteer)