You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.1 KiB
118 lines
3.1 KiB
autofs-5.1.2 - limit getgrgid_r() buffer size |
|
|
|
From: Ian Kent <raven@themaw.net> |
|
|
|
Some older versions of glibc use stack allocation to store group |
|
information during calls to getgrgid_r(). But before doing this |
|
it checks if the size of the response info. can fit in the user |
|
supplied buffer and returns ERANGE if it can't. |
|
|
|
Now automount(8) doesn't check if the size of the buffer it is |
|
passing is larger than it's stack size. That's not vey accurrate |
|
since current stack usage isn't known but better than not checking |
|
at all. |
|
|
|
Signed-off-by: Ian Kent <raven@themaw.net> |
|
--- |
|
CHANGELOG | 1 + |
|
lib/mounts.c | 47 +++++++++++++++++++++++++++++++++-------------- |
|
2 files changed, 34 insertions(+), 14 deletions(-) |
|
|
|
--- autofs-5.0.7.orig/CHANGELOG |
|
+++ autofs-5.0.7/CHANGELOG |
|
@@ -248,6 +248,7 @@ |
|
- improve scalability of direct mount path component. |
|
- fix invalid reference in remount_active_mount(). |
|
- increase worker thread per-thread stack size. |
|
+- limit getgrgid_r() buffer size. |
|
|
|
25/07/2012 autofs-5.0.7 |
|
======================= |
|
--- autofs-5.0.7.orig/lib/mounts.c |
|
+++ autofs-5.0.7/lib/mounts.c |
|
@@ -48,6 +48,9 @@ static const char mnt_name_template[] |
|
static struct kernel_mod_version kver = {0, 0}; |
|
static const char kver_options_template[] = "fd=%d,pgrp=%u,minproto=3,maxproto=5"; |
|
|
|
+extern size_t detached_thread_stack_size; |
|
+static size_t maxgrpbuf = 0; |
|
+ |
|
#define EXT_MOUNTS_HASH_SIZE 50 |
|
|
|
struct ext_mount { |
|
@@ -1503,14 +1506,22 @@ void set_tsd_user_vars(unsigned int logo |
|
} |
|
|
|
gr_tmp = NULL; |
|
+ status = ERANGE; |
|
+ if (!maxgrpbuf) |
|
+ maxgrpbuf = detached_thread_stack_size * 0.9; |
|
+ |
|
+ /* If getting the group name fails go on without it. It's |
|
+ * used to set an environment variable for program maps |
|
+ * which may or may not use it so it isn't critical to |
|
+ * operation. |
|
+ */ |
|
+ |
|
tmplen = grplen; |
|
while (1) { |
|
char *tmp = realloc(gr_tmp, tmplen + 1); |
|
if (!tmp) { |
|
error(logopt, "failed to malloc buffer for getgrgid_r"); |
|
- if (gr_tmp) |
|
- free(gr_tmp); |
|
- goto free_tsv_home; |
|
+ goto no_group; |
|
} |
|
gr_tmp = tmp; |
|
pgr = &gr; |
|
@@ -1519,22 +1530,29 @@ void set_tsd_user_vars(unsigned int logo |
|
if (status != ERANGE) |
|
break; |
|
tmplen += grplen; |
|
+ |
|
+ /* Don't tempt glibc to alloca() larger than is (likely) |
|
+ * available on the stack. |
|
+ */ |
|
+ if (tmplen < maxgrpbuf) |
|
+ continue; |
|
+ |
|
+ /* Add a message so we know this happened */ |
|
+ debug(logopt, "group buffer allocation would be too large"); |
|
+ break; |
|
} |
|
|
|
- if (status || !pgr) { |
|
+no_group: |
|
+ if (status || !pgr) |
|
error(logopt, "failed to get group info from getgrgid_r"); |
|
- free(gr_tmp); |
|
- goto free_tsv_home; |
|
+ else { |
|
+ tsv->group = strdup(gr.gr_name); |
|
+ if (!tsv->group) |
|
+ error(logopt, "failed to malloc buffer for group"); |
|
} |
|
|
|
- tsv->group = strdup(gr.gr_name); |
|
- if (!tsv->group) { |
|
- error(logopt, "failed to malloc buffer for group"); |
|
+ if (gr_tmp) |
|
free(gr_tmp); |
|
- goto free_tsv_home; |
|
- } |
|
- |
|
- free(gr_tmp); |
|
|
|
status = pthread_setspecific(key_thread_stdenv_vars, tsv); |
|
if (status) { |
|
@@ -1545,7 +1563,8 @@ void set_tsd_user_vars(unsigned int logo |
|
return; |
|
|
|
free_tsv_group: |
|
- free(tsv->group); |
|
+ if (tsv->group) |
|
+ free(tsv->group); |
|
free_tsv_home: |
|
free(tsv->home); |
|
free_tsv_user:
|
|
|