Thread (20 messages) 20 messages, 3 authors, 2019-10-02

Re: [PATCH 1/2] apparmor: Use a memory pool instead per-CPU caches

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: 2019-05-02 13:47:37

On 2019-05-02 22:17:35 [+0900], Tetsuo Handa wrote:
There is 'The "too small to fail" memory-allocation rule'
( https://lwn.net/Articles/627419/ ) where GFP_KERNEL allocation for
size <= 32768 bytes never fails unless current thread was killed by
the OOM killer. This means that kmalloc() in

+char *aa_get_buffer(void)
+{
+	union aa_buffer *aa_buf;
+
+try_again:
+	spin_lock(&aa_buffers_lock);
+	if (!list_empty(&aa_global_buffers)) {
+		aa_buf = list_first_entry(&aa_global_buffers, union aa_buffer,
+					  list);
+		list_del(&aa_buf->list);
+		spin_unlock(&aa_buffers_lock);
+		return &aa_buf->buffer[0];
+	}
+	spin_unlock(&aa_buffers_lock);
+
+	aa_buf = kmalloc(aa_g_path_max, GFP_KERNEL);
+	if (WARN_ON_ONCE(!aa_buf))
+		goto try_again;
+	return &aa_buf->buffer[0];
+}

can't return NULL unless current thread was killed by the OOM killer
if aa_g_path_max <= 32768. On the other hand, if aa_g_path_max > 32768,
this allocation can easily fail, and retrying forever is very bad.
as I pointed out in the other email, it shouldn't retry forever because
we should have something in the pool which will be returned.
If current thread was killed by the OOM killer, current thread should be
able to bail out without retrying. If allocation can never succeed (e.g.
aa_g_path_max == 1073741824 was specified), we must bail out.
okay. That is obviously too much and we would loop, indeed.
By the way, did you really test your patch?
I booted Debian on a 112 core which has apparmor enabled and debian
ships a few profiles. And then I used the box for a while.
quoted
@@ -1399,6 +1404,7 @@ static int param_set_aauint(const char *val, const struct kernel_param *kp)
 		return -EPERM;
 
 	error = param_set_uint(val, kp);
+	aa_g_path_max = min_t(uint32_t, aa_g_path_max, sizeof(union aa_buffer));
I think that this will guarantee that aa_g_path_max <= sizeof(struct list_head)
which is too small to succeed. :-(
Ach right, this should have been max instead of min. Btw: are there any
sane upper/lower limits while at it?
quoted
 	pr_info("AppArmor: buffer size set to %d bytes\n", aa_g_path_max);
 
 	return error;
Sebastian
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help