simplify parsing of /etc/busybox.conf

function                                             old     new   delta
parse_config_file                                    799     667    -132

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2011-05-16 00:01:08 +02:00
parent e0238f852b
commit 4566e172eb
3 changed files with 33 additions and 47 deletions

View File

@ -236,8 +236,7 @@ IF_FEATURE_SUID(static uid_t ruid;) /* real uid */
/* applets[] is const, so we have to define this "override" structure */ /* applets[] is const, so we have to define this "override" structure */
static struct BB_suid_config { static struct BB_suid_config {
int m_applet; int m_applet;
uid_t m_uid; struct bb_uidgid_t m_ugid;
gid_t m_gid;
mode_t m_mode; mode_t m_mode;
struct BB_suid_config *m_next; struct BB_suid_config *m_next;
} *suid_config; } *suid_config;
@ -295,8 +294,6 @@ static const unsigned short mode_mask[] ALIGN2 = {
0, S_IXOTH, S_IXOTH, 0 /* other */ 0, S_IXOTH, S_IXOTH, 0 /* other */
}; };
#define parse_error(x) do { errmsg = x; goto pe_label; } while (0)
static void parse_config_file(void) static void parse_config_file(void)
{ {
struct BB_suid_config *sct_head; struct BB_suid_config *sct_head;
@ -312,8 +309,6 @@ static void parse_config_file(void)
char buffer[256]; char buffer[256];
struct stat st; struct stat st;
assert(!suid_config); /* Should be set to NULL by bss init. */
ruid = getuid(); ruid = getuid();
if (ruid == 0) /* run by root - don't need to even read config file */ if (ruid == 0) /* run by root - don't need to even read config file */
return; return;
@ -335,10 +330,11 @@ static void parse_config_file(void)
s = buffer; s = buffer;
if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */ if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */
// why? // Looks like bloat
if (ferror(f)) { /* Make sure it wasn't a read error. */ //if (ferror(f)) { /* Make sure it wasn't a read error. */
parse_error("reading"); // errmsg = "reading";
} // goto pe_label;
//}
fclose(f); fclose(f);
suid_config = sct_head; /* Success, so set the pointer. */ suid_config = sct_head; /* Success, so set the pointer. */
return; return;
@ -355,7 +351,8 @@ static void parse_config_file(void)
* we do err on the side of caution. Besides, the line would be * we do err on the side of caution. Besides, the line would be
* too long if it did end with a newline. */ * too long if it did end with a newline. */
if (!strchr(s, '\n') && !feof(f)) { if (!strchr(s, '\n') && !feof(f)) {
parse_error("line too long"); errmsg = "line too long";
goto pe_label;
} }
/* Trim leading and trailing whitespace, ignoring comments, and /* Trim leading and trailing whitespace, ignoring comments, and
@ -376,7 +373,8 @@ static void parse_config_file(void)
|| e[1] /* Trailing characters? */ || e[1] /* Trailing characters? */
|| !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */ || !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */
) { ) {
parse_error("section header"); errmsg = "section header";
goto pe_label;
} }
/* Right now we only have one section so just check it. /* Right now we only have one section so just check it.
* If more sections are added in the future, please don't * If more sections are added in the future, please don't
@ -406,7 +404,8 @@ static void parse_config_file(void)
s = get_trimmed_slice(s, e); s = get_trimmed_slice(s, e);
} }
if (!e || !*s) { /* Missing '=' or empty key. */ if (!e || !*s) { /* Missing '=' or empty key. */
parse_error("keyword"); errmsg = "keyword";
goto pe_label;
} }
/* Ok, we have an applet name. Process the rhs if this /* Ok, we have an applet name. Process the rhs if this
@ -419,9 +418,9 @@ static void parse_config_file(void)
* The last config line for each applet will be the * The last config line for each applet will be the
* one used since we insert at the head of the list. * one used since we insert at the head of the list.
* I suppose this could be considered a feature. */ * I suppose this could be considered a feature. */
sct = xmalloc(sizeof(struct BB_suid_config)); sct = xzalloc(sizeof(*sct));
sct->m_applet = applet_no; sct->m_applet = applet_no;
sct->m_mode = 0; /*sct->m_mode = 0;*/
sct->m_next = sct_head; sct->m_next = sct_head;
sct_head = sct; sct_head = sct;
@ -436,7 +435,8 @@ static void parse_config_file(void)
const char *q; const char *q;
q = strchrnul(mode_chars + 5*i, *e++); q = strchrnul(mode_chars + 5*i, *e++);
if (!*q) { if (!*q) {
parse_error("mode"); errmsg = "mode";
goto pe_label;
} }
/* Adjust by -i to account for nul. */ /* Adjust by -i to account for nul. */
sct->m_mode |= mode_mask[(q - mode_chars) - i]; sct->m_mode |= mode_mask[(q - mode_chars) - i];
@ -449,29 +449,14 @@ static void parse_config_file(void)
/* Note: we require whitespace between the mode and the /* Note: we require whitespace between the mode and the
* user/group info. */ * user/group info. */
if ((s == e) || !(e = strchr(s, '.'))) { if ((s == e) || !(e = strchr(s, '.'))) {
parse_error("<uid>.<gid>"); errmsg = "uid.gid";
} goto pe_label;
*e++ = '\0';
/* We can't use get_ug_id here since it would exit()
* if a uid or gid was not found. Oh well... */
sct->m_uid = bb_strtoul(s, NULL, 10);
if (errno) {
struct passwd *pwd = getpwnam(s);
if (!pwd) {
parse_error("user");
}
sct->m_uid = pwd->pw_uid;
} }
sct->m_gid = bb_strtoul(e, NULL, 10); *e++ = ':'; /* get_uidgid doesn't understand user.group */
if (errno) { if (get_uidgid(&sct->m_ugid, s, /*allow_numeric:*/ 1) == 0) {
struct group *grp; errmsg = "unknown user/group";
grp = getgrnam(e); goto pe_label;
if (!grp) {
parse_error("group");
}
sct->m_gid = grp->gr_gid;
} }
} }
continue; continue;
@ -485,14 +470,14 @@ static void parse_config_file(void)
* We may want to simply ignore such lines in case they * We may want to simply ignore such lines in case they
* are used in some future version of busybox. */ * are used in some future version of busybox. */
if (!section) { if (!section) {
parse_error("keyword outside section"); errmsg = "keyword outside section";
goto pe_label;
} }
} /* while (1) */ } /* while (1) */
pe_label: pe_label:
fprintf(stderr, "Parse error in %s, line %d: %s\n", bb_error_msg("parse error in %s, line %u: %s", config_file, lc, errmsg);
config_file, lc, errmsg);
fclose(f); fclose(f);
/* Release any allocated memory before returning. */ /* Release any allocated memory before returning. */
@ -532,10 +517,10 @@ static void check_suid(int applet_no)
goto check_need_suid; goto check_need_suid;
found: found:
m = sct->m_mode; m = sct->m_mode;
if (sct->m_uid == ruid) if (sct->m_ugid.uid == ruid)
/* same uid */ /* same uid */
m >>= 6; m >>= 6;
else if ((sct->m_gid == rgid) || ingroup(ruid, sct->m_gid)) else if ((sct->m_ugid.gid == rgid) || ingroup(ruid, sct->m_ugid.gid))
/* same group / in group */ /* same group / in group */
m >>= 3; m >>= 3;
@ -544,7 +529,7 @@ static void check_suid(int applet_no)
/* _both_ sgid and group_exec have to be set for setegid */ /* _both_ sgid and group_exec have to be set for setegid */
if ((sct->m_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) if ((sct->m_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
rgid = sct->m_gid; rgid = sct->m_ugid.gid;
/* else (no setegid) we will set egid = rgid */ /* else (no setegid) we will set egid = rgid */
/* We set effective AND saved ids. If saved-id is not set /* We set effective AND saved ids. If saved-id is not set
@ -555,7 +540,7 @@ static void check_suid(int applet_no)
/* do we have to set effective uid? */ /* do we have to set effective uid? */
uid = ruid; uid = ruid;
if (sct->m_mode & S_ISUID) if (sct->m_mode & S_ISUID)
uid = sct->m_uid; uid = sct->m_ugid.uid;
/* else (no seteuid) we will set euid = ruid */ /* else (no seteuid) we will set euid = ruid */
if (setresuid(-1, uid, uid)) if (setresuid(-1, uid, uid))

View File

@ -71,7 +71,8 @@ int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
} }
} }
gr = getgrnam(group); gr = getgrnam(group);
if (!gr) return 0; if (!gr)
return 0;
u->gid = gr->gr_gid; u->gid = gr->gr_gid;
} }
return 1; return 1;

View File

@ -292,7 +292,7 @@ static void make_device(char *path, int delete)
* the rest the line unless keep_matching == 1 */ * the rest the line unless keep_matching == 1 */
/* 2nd field: uid:gid - device ownership */ /* 2nd field: uid:gid - device ownership */
if (get_uidgid(&ugid, tokens[1], 1) == 0) if (get_uidgid(&ugid, tokens[1], /*allow_numeric:*/ 1) == 0)
bb_error_msg("unknown user/group %s on line %d", tokens[1], parser->lineno); bb_error_msg("unknown user/group %s on line %d", tokens[1], parser->lineno);
/* 3rd field: mode - device permissions */ /* 3rd field: mode - device permissions */