summaryrefslogtreecommitdiff
path: root/src/misc
diff options
context:
space:
mode:
Diffstat (limited to 'src/misc')
-rw-r--r--src/misc/initgroups.c26
-rw-r--r--src/misc/mntent.c12
2 files changed, 32 insertions, 6 deletions
diff --git a/src/misc/initgroups.c b/src/misc/initgroups.c
index 922a9581..101f5c7b 100644
--- a/src/misc/initgroups.c
+++ b/src/misc/initgroups.c
@@ -1,11 +1,29 @@
#define _GNU_SOURCE
#include <grp.h>
#include <limits.h>
+#include <stdlib.h>
int initgroups(const char *user, gid_t gid)
{
- gid_t groups[NGROUPS_MAX];
- int count = NGROUPS_MAX;
- if (getgrouplist(user, gid, groups, &count) < 0) return -1;
- return setgroups(count, groups);
+ gid_t buf[32], *groups = buf;
+ int count = sizeof buf / sizeof *buf, prev_count = count;
+ while (getgrouplist(user, gid, groups, &count) < 0) {
+ if (groups != buf) free(groups);
+
+ /* Return if failure isn't buffer size */
+ if (count <= prev_count)
+ return -1;
+
+ /* Always increase by at least 50% to limit to
+ * logarithmically many retries on TOCTOU races. */
+ if (count < prev_count + (prev_count>>1))
+ count = prev_count + (prev_count>>1);
+
+ groups = calloc(count, sizeof *groups);
+ if (!groups) return -1;
+ prev_count = count;
+ }
+ int ret = setgroups(count, groups);
+ if (groups != buf) free(groups);
+ return ret;
}
diff --git a/src/misc/mntent.c b/src/misc/mntent.c
index 78bf0cd0..76f9c162 100644
--- a/src/misc/mntent.c
+++ b/src/misc/mntent.c
@@ -81,7 +81,7 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle
len = strlen(linebuf);
if (len > INT_MAX) continue;
for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len;
- sscanf(linebuf, " %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %d %d",
+ sscanf(linebuf, " %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %d %d",
n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
&mnt->mnt_freq, &mnt->mnt_passno);
} while (linebuf[n[0]] == '#' || n[1]==len);
@@ -115,5 +115,13 @@ int addmntent(FILE *f, const struct mntent *mnt)
char *hasmntopt(const struct mntent *mnt, const char *opt)
{
- return strstr(mnt->mnt_opts, opt);
+ size_t l = strlen(opt);
+ char *p = mnt->mnt_opts;
+ for (;;) {
+ if (!strncmp(p, opt, l) && (!p[l] || p[l]==',' || p[l]=='='))
+ return p;
+ p = strchr(p, ',');
+ if (!p) return 0;
+ p++;
+ }
}